quota updates, V3
Subsystems (2)
cover quota updates, V3
Changes from version 2:
- rework quota statistics to use the common xfs_stats.c code
- address various minor issues pointed out during review
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
PATCH 1/8 xfs: merge xfs_qm_export_dquot into xfs_qm_scall_getquota
The is no good reason to have these two separate, and for the next change we would need the full struct xfs_dquot in xfs_qm_export_dquot, so better just fold the code now instead of changing it spuriously.
fs/xfs/xfs_qm_syscalls.c +49 -69
@@ -47,9 +47,6 @@ STATIC int xfs_qm_log_quotaoff_end(xfs_m uint); STATIC uint xfs_qm_export_flags(uint); STATIC uint xfs_qm_export_qtype_flags(uint); -STATIC void xfs_qm_export_dquot(xfs_mount_t *, xfs_disk_dquot_t *, -fs_disk_quota_t *); -/* * Turn off quota accounting and/or enforcement for all udquots and/or
@@ -635,42 +632,6 @@ xfs_qm_scall_setqlim(return error; } -int -xfs_qm_scall_getquota ( -xfs_mount_t *mp, -xfs_dqid_t id, -uint type, -fs_disk_quota_t *out) -{ -xfs_dquot_t *dqp; -int error; - -/* -* Try to get the dquot. We don't want it allocated on disk, so -* we aren't passing the XFS_QMOPT_DOALLOC flag. If it doesn't -* exist, we'll get ENOENT back. -*/ -if ((error =xfs_qm_dqget (mp,NULL , id, type,0 , &dqp))) { -return (error); - } - -/* -* If everything's NULL, this dquot doesn't quite exist as far as -* our utility programs are concerned. -*/ -if (XFS_IS_DQUOT_UNINITIALIZED (dqp)) { -xfs_qm_dqput (dqp); -return XFS_ERROR (ENOENT ); - } -/* -* Convert the disk dquot to the exportable format -*/ -xfs_qm_export_dquot (mp, &dqp->q_core, out); -xfs_qm_dqput (dqp); -return (error ?XFS_ERROR (EFAULT ) :0 ); -} - - STATIC int xfs_qm_log_quotaoff_end( xfs_mount_t *mp,
@@ -759,50 +720,66 @@ error0: } -/* -* Translate an internal style on-disk-dquot to the exportable format. -* The main differences are that the counters/limits are all in Basic -* Blocks (BBs) instead of the internal FSBs, and all on-disk data has -* to be converted to the native endianness. -*/ -STATIC void -xfs_qm_export_dquot ( -xfs_mount_t *mp, -xfs_disk_dquot_t *src, +int +xfs_qm_scall_getquota ( +struct xfs_mount *mp, +xfs_dqid_t id, +uint type,struct fs_disk_quota *dst) { +struct xfs_dquot *dqp; +int error; + +/* +* Try to get the dquot. We don't want it allocated on disk, so +* we aren't passing the XFS_QMOPT_DOALLOC flag. If it doesn't +* exist, we'll get ENOENT back. +*/ + error =xfs_qm_dqget (mp,NULL , id, type,0 , &dqp); +if (error) +return error; + +/* +* If everything's NULL, this dquot doesn't quite exist as far as +* our utility programs are concerned. +*/ +if (XFS_IS_DQUOT_UNINITIALIZED (dqp)) { + error =XFS_ERROR (ENOENT ); + goto out_put; + } +memset (dst,0 ,sizeof (*dst)); - dst->d_version =FS_DQUOT_VERSION ;/* different from src->d_version */ - dst->d_flags =xfs_qm_export_qtype_flags (src->d_flags); - dst->d_id =be32_to_cpu (src->d_id); + dst->d_version =FS_DQUOT_VERSION ; + dst->d_flags =xfs_qm_export_qtype_flags (dqp->q_core.d_flags); + dst->d_id =be32_to_cpu (dqp->q_core.d_id); dst->d_blk_hardlimit = -XFS_FSB_TO_BB (mp,be64_to_cpu (src->d_blk_hardlimit)); +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 (src->d_blk_softlimit)); - dst->d_ino_hardlimit =be64_to_cpu (src->d_ino_hardlimit); - dst->d_ino_softlimit =be64_to_cpu (src->d_ino_softlimit); - dst->d_bcount =XFS_FSB_TO_BB (mp,be64_to_cpu (src->d_bcount)); - dst->d_icount =be64_to_cpu (src->d_icount); - dst->d_btimer =be32_to_cpu (src->d_btimer); - dst->d_itimer =be32_to_cpu (src->d_itimer); - dst->d_iwarns =be16_to_cpu (src->d_iwarns); - dst->d_bwarns =be16_to_cpu (src->d_bwarns); +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_softlimit =be64_to_cpu (dqp->q_core.d_ino_softlimit); + dst->d_bcount =XFS_FSB_TO_BB (mp,be64_to_cpu (dqp->q_core.d_bcount)); + dst->d_icount =be64_to_cpu (dqp->q_core.d_icount); + dst->d_btimer =be32_to_cpu (dqp->q_core.d_btimer); + dst->d_itimer =be32_to_cpu (dqp->q_core.d_itimer); + dst->d_iwarns =be16_to_cpu (dqp->q_core.d_iwarns); + dst->d_bwarns =be16_to_cpu (dqp->q_core.d_bwarns); dst->d_rtb_hardlimit = -XFS_FSB_TO_BB (mp,be64_to_cpu (src->d_rtb_hardlimit)); +XFS_FSB_TO_BB (mp,be64_to_cpu (dqp->q_core.d_rtb_hardlimit)); dst->d_rtb_softlimit = -XFS_FSB_TO_BB (mp,be64_to_cpu (src->d_rtb_softlimit)); - dst->d_rtbcount =XFS_FSB_TO_BB (mp,be64_to_cpu (src->d_rtbcount)); - dst->d_rtbtimer =be32_to_cpu (src->d_rtbtimer); - dst->d_rtbwarns =be16_to_cpu (src->d_rtbwarns); +XFS_FSB_TO_BB (mp,be64_to_cpu (dqp->q_core.d_rtb_softlimit)); + dst->d_rtbcount =XFS_FSB_TO_BB (mp,be64_to_cpu (dqp->q_core.d_rtbcount)); + dst->d_rtbtimer =be32_to_cpu (dqp->q_core.d_rtbtimer); + dst->d_rtbwarns =be16_to_cpu (dqp->q_core.d_rtbwarns);/* * Internally, we don't reset all the timers when quota enforcement * gets turned off. No need to confuse the user level code, * so return zeroes in that case. */ -if ((!XFS_IS_UQUOTA_ENFORCED (mp) && src->d_flags ==XFS_DQ_USER ) || +if ((!XFS_IS_UQUOTA_ENFORCED (mp) && dqp->q_core.d_flags ==XFS_DQ_USER ) || (!XFS_IS_OQUOTA_ENFORCED (mp) && - (src->d_flags & (XFS_DQ_PROJ |XFS_DQ_GROUP )))) { + (dqp->q_core.d_flags & (XFS_DQ_PROJ |XFS_DQ_GROUP )))) { dst->d_btimer =0 ; dst->d_itimer =0 ; dst->d_rtbtimer =0 ;
@@ -823,6 +800,9 @@ xfs_qm_export_dquot( } }#endif +out_put: +xfs_qm_dqput (dqp); +return error; }STATIC uint
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 1/8] xfs: merge xfs_qm_export_dquot into xfs_qm_scall_getquota
Hi Christoph,
Quoted 6 lines · Christoph Hellwig
The is no good reason to have these two separate, and for the next change we would need the full struct
xfs_dquotinxfs_qm_export_dquot, so better just fold the code now instead of changing it spuriously.Reviewed-by Dave Chinner <[email protected]>Signed-off-by Christoph Hellwig <[email protected]>
I should have replied to this patch, not the older rev.
I have a question about the error code, now we're not mapping errors to EFAULT and we used do... which is correct?
Thanks,
Ben
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 1/8] xfs: merge xfs_qm_export_dquot into xfs_qm_scall_getquota
Quoted 4 lines
I should have replied to this patch, not the older rev.
I have a question about the error code, now we're not mapping errors to EFAULT and we used do... which is correct?
The old one looks finshy, but we even if we changed it it should be in a separate patch with a good description. I'll resend with this bit fixed.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 1/8] xfs: merge xfs_qm_export_dquot into xfs_qm_scall_getquota
Quoted 8 lines · Christoph Hellwig
Quoted 4 lines
I should have replied to this patch, not the older rev.
I have a question about the error code, now we're not mapping errors to EFAULT and we used do... which is correct?
The old one looks finshy, but we even if we changed it it should be in a separate patch with a good description. I'll resend with this bit fixed.
Sounds great. ;)
-Ben
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 1/8] xfs: merge xfs_qm_export_dquot into xfs_qm_scall_getquota
Quoted 11 lines · Ben Myers
Quoted 8 lines · Christoph Hellwig
Quoted 4 lines
I should have replied to this patch, not the older rev.
I have a question about the error code, now we're not mapping errors to EFAULT and we used do... which is correct?
The old one looks finshy, but we even if we changed it it should be in a separate patch with a good description. I'll resend with this bit fixed.
Sounds great. ;)
Actually the patch is fine as-is. If you look at the old xfs_qm_scall_getquota we'd return any error we get from xfs_qm_dqget as-is, and return ENOENT if XFS_IS_DQUOT_UNINITIALIZED is true. The place where any other error is converted to EFAULT is never actually reached.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Ben Myers
Reviewed-byRe: [PATCH 1/8] xfs: merge xfs_qm_export_dquot into xfs_qm_scall_getquota
Quoted 11 lines · Christoph Hellwig
Quoted 10 lines · Ben Myers
Quoted 8 lines · Christoph Hellwig
Quoted 4 lines
I should have replied to this patch, not the older rev.
I have a question about the error code, now we're not mapping errors to EFAULT and we used do... which is correct?
The old one looks finshy, but we even if we changed it it should be in a separate patch with a good description. I'll resend with this bit fixed.
Quoted 7 lines
Quoted 1 line
Sounds great. ;)
Actually the patch is fine as-is. If you look at the old
xfs_qm_scall_getquotawe'd return any error we get fromxfs_qm_dqgetas-is, and return ENOENT ifXFS_IS_DQUOT_UNINITIALIZEDis true. The place where any other error is converted to EFAULT is never actually reached.
Apologies.. I see it now.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
PATCH 2/8 xfs: include reservations in quota reporting
In reply to Christoph HellwigReport all quota usage including the currently pending reservations. This avoids the need to flush delalloc space before gathering quota information, and matches quota enforcement, which already takes the reservations into account.
This fixes xfstests 270.
fs/xfs/xfs_qm_bhv.c +12 -12
@@ -40,28 +40,28 @@ STATIC voidxfs_fill_statvfs_from_dquot (struct kstatfs *statp, -xfs_disk_dquot_t *dp) +struct xfs_dquot *dqp) {__uint64_t limit; - limit = dp->d_blk_softlimit ? -be64_to_cpu (dp->d_blk_softlimit) : -be64_to_cpu (dp->d_blk_hardlimit); + limit = dqp->q_core.d_blk_softlimit ? +be64_to_cpu (dqp->q_core.d_blk_softlimit) : +be64_to_cpu (dqp->q_core.d_blk_hardlimit);if (limit && statp->f_blocks > limit) { statp->f_blocks = limit; statp->f_bfree = statp->f_bavail = - (statp->f_blocks >be64_to_cpu (dp->d_bcount)) ? - (statp->f_blocks -be64_to_cpu (dp->d_bcount)) :0 ; + (statp->f_blocks > dqp->q_res_bcount) ? + (statp->f_blocks - dqp->q_res_bcount) :0 ; } - limit = dp->d_ino_softlimit ? -be64_to_cpu (dp->d_ino_softlimit) : -be64_to_cpu (dp->d_ino_hardlimit); + limit = dqp->q_core.d_ino_softlimit ? +be64_to_cpu (dqp->q_core.d_ino_softlimit) : +be64_to_cpu (dqp->q_core.d_ino_hardlimit);if (limit && statp->f_files > limit) { statp->f_files = limit; statp->f_ffree = - (statp->f_files >be64_to_cpu (dp->d_icount)) ? - (statp->f_ffree -be64_to_cpu (dp->d_icount)) :0 ; + (statp->f_files > dqp->q_res_icount) ? + (statp->f_ffree - dqp->q_res_icount) :0 ; } }
@@ -82,7 +82,7 @@ xfs_qm_statvfs(xfs_dquot_t *dqp;if (!xfs_qm_dqget (mp,NULL ,xfs_get_projid (ip),XFS_DQ_PROJ ,0 , &dqp)) { -xfs_fill_statvfs_from_dquot (statp, &dqp->q_core); +xfs_fill_statvfs_from_dquot (statp, dqp);xfs_qm_dqput (dqp); } }
fs/xfs/xfs_qm_syscalls.c +3 -3
@@ -758,8 +758,8 @@ xfs_qm_scall_getquota(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_softlimit =be64_to_cpu (dqp->q_core.d_ino_softlimit); - dst->d_bcount =XFS_FSB_TO_BB (mp,be64_to_cpu (dqp->q_core.d_bcount)); - dst->d_icount =be64_to_cpu (dqp->q_core.d_icount); + dst->d_bcount =XFS_FSB_TO_BB (mp, dqp->q_res_bcount); + dst->d_icount = dqp->q_res_icount; dst->d_btimer =be32_to_cpu (dqp->q_core.d_btimer); dst->d_itimer =be32_to_cpu (dqp->q_core.d_itimer); dst->d_iwarns =be16_to_cpu (dqp->q_core.d_iwarns);
@@ -768,7 +768,7 @@ xfs_qm_scall_getquota(XFS_FSB_TO_BB (mp,be64_to_cpu (dqp->q_core.d_rtb_hardlimit)); dst->d_rtb_softlimit =XFS_FSB_TO_BB (mp,be64_to_cpu (dqp->q_core.d_rtb_softlimit)); - dst->d_rtbcount =XFS_FSB_TO_BB (mp,be64_to_cpu (dqp->q_core.d_rtbcount)); + dst->d_rtbcount =XFS_FSB_TO_BB (mp, dqp->q_res_rtbcount); dst->d_rtbtimer =be32_to_cpu (dqp->q_core.d_rtbtimer); dst->d_rtbwarns =be16_to_cpu (dqp->q_core.d_rtbwarns);
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 2/8] xfs: include reservations in quota reporting
Quoted 9 lines · Christoph Hellwig
Report all quota usage including the currently pending reservations. This avoids the need to flush delalloc space before gathering quota information, and matches quota enforcement, which already takes the reservations into account.
This fixes xfstests 270.
Reviewed-by Dave Chinner <[email protected]>Signed-off-by Christoph Hellwig <[email protected]>
I'm a little concerned about large speculative delay block reservations with this code, but that remains to be seen.
Looks good.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
PATCH 3/8 quota: make Q_XQUOTASYNC a noop
In reply to Christoph HellwigNow that XFS takes quota reservations into account there is no need to flush anything before reporting quotas - in addition to beeing fully transactional all quota information is also 100% coherent with the rest of the filesystem now.
fs/quota/quota.c +1 -2
@@ -282,10 +282,9 @@ static int do_quotactl(struct super_bloccase Q_XGETQUOTA :return quota_getxquota (sb, type, id, addr);case Q_XQUOTASYNC : -/* caller already holds s_umount */ if (sb->s_flags &MS_RDONLY )return -EROFS ; -writeback_inodes_sb (sb,WB_REASON_SYNC ); +/* XFS quotas are fully coherent now, making this call a noop */ return 0 ;default :return -EINVAL ;
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 3/8] quota: make Q_XQUOTASYNC a noop
Quoted 7 lines · Christoph Hellwig
Now that XFS takes quota reservations into account there is no need to flush anything before reporting quotas - in addition to beeing fully transactional all quota information is also 100% coherent with the rest of the filesystem now.
Reviewed-by Dave Chinner <[email protected]>Signed-off-by Christoph Hellwig <[email protected]>
Looks good. IIRC there were also some userspace bits related to this awhile ago.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
PATCH 4/8 xfs: use common code for quota statistics
In reply to Christoph HellwigSwitch the quota code over to use the generic XFS statistics infrastructure. While the legacy /proc/fs/xfs/xqm and /proc/fs/xfs/xqmstats interfaces are preserved for now the statistics that still have a meaning with the current code are now also available from /proc/fs/xfs/stats.
--- fs/xfs/xfs_dquot.c | 14 +++--- fs/xfs/xfs_qm.c | 9 ++-- fs/xfs/xfs_qm.h | 2 fs/xfs/xfs_qm_bhv.c | 2 fs/xfs/xfs_qm_stats.c | 105 -------------------------------------------------- fs/xfs/xfs_qm_stats.h | 53 ------------------------- fs/xfs/xfs_stats.c | 92 ++++++++++++++++++++++++++++++++++++++----- fs/xfs/xfs_stats.h | 10 ++++ 8 files changed, 103 insertions(+), 184 deletions(-)
fs/xfs/xfs_dquot.c +8 -6
@@ -74,7 +74,7 @@ xfs_qm_dqdestroy(mutex_destroy (&dqp->q_qlock);kmem_zone_free (xfs_Gqm->qm_dqzone, dqp); -atomic_dec (&xfs_Gqm->qm_totaldquots); +XFS_STATS_DEC (xs_qm_dquot); }/*
@@ -516,7 +516,7 @@ xfs_qm_dqread(if (!(type &XFS_DQ_USER ))lockdep_set_class (&dqp->q_qlock, &xfs_dquot_other_class); -atomic_inc (&xfs_Gqm->qm_totaldquots); +XFS_STATS_INC (xs_qm_dquot);trace_xfs_dqread (dqp);
@@ -712,12 +712,12 @@ restart:*/ switch (xfs_qm_dqlookup (mp, id, h, O_dqpp)) {case -1 : -XQM_STATS_INC (xqmstats.xs_qm_dquot_dups); +XFS_STATS_INC (xs_qm_dquot_dups);mutex_unlock (&h->qh_lock);delay (1 ); goto restart;case 0 : -XQM_STATS_INC (xqmstats.xs_qm_dqcachehits); +XFS_STATS_INC (xs_qm_dqcachehits);/* * The dquot was found, moved to the front of the chain, * taken off the freelist if it was on it, and locked
@@ -729,7 +729,7 @@ restart:trace_xfs_dqget_hit (*O_dqpp);return 0 ;/* success */ default : -XQM_STATS_INC (xqmstats.xs_qm_dqcachemisses); +XFS_STATS_INC (xs_qm_dqcachemisses);break ; }
@@ -804,7 +804,7 @@ restart:xfs_qm_dqput (tmpdqp);mutex_unlock (&h->qh_lock);xfs_qm_dqdestroy (dqp); -XQM_STATS_INC (xqmstats.xs_qm_dquot_dups); +XFS_STATS_INC (xs_qm_dquot_dups); goto restart;default :break ;
@@ -873,6 +873,7 @@ recurse:if (list_empty (&dqp->q_freelist)) {list_add_tail (&dqp->q_freelist, &xfs_Gqm->qm_dqfrlist); xfs_Gqm->qm_dqfrlist_cnt++; +XFS_STATS_INC (xs_qm_dquot_unused); }mutex_unlock (&xfs_Gqm->qm_dqfrlist_lock);
@@ -1189,6 +1190,7 @@ xfs_qm_dqpurge(ASSERT (!list_empty (&dqp->q_freelist));list_del_init (&dqp->q_freelist); xfs_Gqm->qm_dqfrlist_cnt--; +XFS_STATS_DEC (xs_qm_dquot_unused);mutex_unlock (&xfs_Gqm->qm_dqfrlist_lock);xfs_qm_dqdestroy (dqp);
fs/xfs/xfs_qm.c +5 -4
@@ -134,7 +134,6 @@ xfs_Gqm_init(void) }else xqm->qm_dqtrxzone = qm_dqtrxzone; -atomic_set (&xqm->qm_totaldquots,0 ); xqm->qm_nrefs =0 ;return xqm;
@@ -1637,10 +1636,11 @@ xfs_qm_dqreclaim_one(xfs_dqunlock (dqp);trace_xfs_dqreclaim_want (dqp); -XQM_STATS_INC (xqmstats.xs_qm_dqwants); +XFS_STATS_INC (xs_qm_dqwants);list_del_init (&dqp->q_freelist); xfs_Gqm->qm_dqfrlist_cnt--; +XFS_STATS_DEC (xs_qm_dquot_unused);return ; }
@@ -1690,9 +1690,10 @@ xfs_qm_dqreclaim_one(ASSERT (dqp->q_nrefs ==0 );list_move_tail (&dqp->q_freelist, dispose_list); xfs_Gqm->qm_dqfrlist_cnt--; +XFS_STATS_DEC (xs_qm_dquot_unused);trace_xfs_dqreclaim_done (dqp); -XQM_STATS_INC (xqmstats.xs_qm_dqreclaims); +XFS_STATS_INC (xs_qm_dqreclaims);return ; out_busy:
@@ -1704,7 +1705,7 @@ out_busy:list_move_tail (&dqp->q_freelist, &xfs_Gqm->qm_dqfrlist);trace_xfs_dqreclaim_busy (dqp); -XQM_STATS_INC (xqmstats.xs_qm_dqreclaim_misses); +XFS_STATS_INC (xs_qm_dqreclaim_misses); }STATIC int
fs/xfs/xfs_qm_stats.c deleted +0 -105
105 lines not on this page · raw message
fs/xfs/xfs_qm_stats.h deleted +0 -53
53 lines not on this page · raw message
fs/xfs/xfs_stats.h +10 -0
@@ -183,6 +183,16 @@ struct xfsstats {__uint32_t xs_ibt_2_alloc;__uint32_t xs_ibt_2_free;__uint32_t xs_ibt_2_moves; +#define XFSSTAT_END_XQMSTAT (XFSSTAT_END_IBT_V2+6) +__uint32_t xs_qm_dqreclaims; +__uint32_t xs_qm_dqreclaim_misses; +__uint32_t xs_qm_dquot_dups; +__uint32_t xs_qm_dqcachemisses; +__uint32_t xs_qm_dqcachehits; +__uint32_t xs_qm_dqwants; +#define XFSSTAT_END_QM (XFSSTAT_END_XQMSTAT+2) +__uint32_t xs_qm_dquot; +__uint32_t xs_qm_dquot_unused;/* Extra precision counters */ __uint64_t xs_xstrat_bytes;__uint64_t xs_write_bytes;
fs/xfs/xfs_qm.h +0 -2
@@ -21,7 +21,6 @@#include "xfs_dquot_item.h" #include "xfs_dquot.h" #include "xfs_quota_priv.h" -#include "xfs_qm_stats.h" struct xfs_qm ;struct xfs_inode ;
@@ -60,7 +59,6 @@ typedef struct xfs_qm {struct list_head qm_dqfrlist;/* freelist of dquots */ struct mutex qm_dqfrlist_lock;int qm_dqfrlist_cnt; -atomic_t qm_totaldquots;/* total incore dquots */ uint qm_nrefs;/* file systems with quota on */ kmem_zone_t *qm_dqzone;/* dquot mem-alloc zone */ kmem_zone_t *qm_dqtrxzone;/* t_dqinfo of transactions */
fs/xfs/xfs_qm_bhv.c +0 -2
@@ -92,13 +92,11 @@ xfs_qm_init(void) {printk (KERN_INFO "SGI XFS Quota Management subsystem\n" );mutex_init (&xfs_Gqm_lock); -xfs_qm_init_procfs (); } void __exitxfs_qm_exit (void ) { -xfs_qm_cleanup_procfs ();if (qm_dqzone)kmem_zone_destroy (qm_dqzone);if (qm_dqtrxzone)
fs/xfs/xfs_stats.c +80 -12
131 lines not on this page · raw message
fs/xfs/Makefile +0 -3
@@ -96,9 +96,6 @@ xfs-$(CONFIG_XFS_QUOTA) += xfs_dquot.o xfs_qm_bhv.o \ xfs_qm.o \ xfs_quotaops.o -ifeq ($(CONFIG_XFS_QUOTA),y) -xfs-$(CONFIG_PROC_FS) += xfs_qm_stats.o -endif xfs-$(CONFIG_XFS_RT) += xfs_rtalloc.o xfs-$(CONFIG_XFS_POSIX_ACL) += xfs_acl.o xfs-$(CONFIG_PROC_FS) += xfs_stats.o
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 4/8] xfs: use common code for quota statistics
Quoted 6 lines · Christoph Hellwig
Switch the quota code over to use the generic XFS statistics infrastructure. While the legacy
/proc/fs/xfs/xqmand/proc/fs/xfs/xqmstatsinterfaces are preserved for now the statistics that still have a meaning with the current code are now also available from/proc/fs/xfs/stats.Signed-off-by Christoph Hellwig <[email protected]>
Looks OK. Just one question/observation, though. This will make the quota proc files show up even even quota is not compiled in. Are there any applications out there that make use of the presence of these files to determine if quota is configured into the kernel or not?
I think I just answered my own question - xfstests does exactly this proc file test in _require_quota(). So I think their presence needs to be conditional on CONFIG_XFS_QUOTA....
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 4/8] xfs: use common code for quota statistics
Quoted 14 lines · Dave Chinner
Quoted 6 lines · Christoph Hellwig
Switch the quota code over to use the generic XFS statistics infrastructure. While the legacy
/proc/fs/xfs/xqmand/proc/fs/xfs/xqmstatsinterfaces are preserved for now the statistics that still have a meaning with the current code are now also available from/proc/fs/xfs/stats.Signed-off-by Christoph Hellwig <[email protected]>Looks OK. Just one question/observation, though. This will make the quota proc files show up even even quota is not compiled in. Are there any applications out there that make use of the presence of these files to determine if quota is configured into the kernel or not?
Quoted 3 lines
I think I just answered my own question - xfstests does exactly this proc file test in
_require_quota(). So I think their presence needs to be conditional onCONFIG_XFS_QUOTA....
Ok, I'll respin it. That also reminds me I didn't bother to test without quotas, which I probably should do as well.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
PATCH v2 4/8 xfs: use common code for quota statistics
In reply to Christoph HellwigSwitch the quota code over to use the generic XFS statistics infrastructure. While the legacy /proc/fs/xfs/xqm and /proc/fs/xfs/xqmstats interfaces are preserved for now the statistics that still have a meaning with the current code are now also available from /proc/fs/xfs/stats.
--- fs/xfs/Makefile | 3 - fs/xfs/xfs_dquot.c | 14 +++--- fs/xfs/xfs_qm.c | 9 ++-- fs/xfs/xfs_qm.h | 2 fs/xfs/xfs_qm_bhv.c | 2 fs/xfs/xfs_qm_stats.c | 105 -------------------------------------------------- fs/xfs/xfs_qm_stats.h | 53 ------------------------- fs/xfs/xfs_stats.c | 99 +++++++++++++++++++++++++++++++++++++++++------ fs/xfs/xfs_stats.h | 10 ++++ 9 files changed, 110 insertions(+), 187 deletions(-)
fs/xfs/xfs_dquot.c +8 -6
@@ -74,7 +74,7 @@ xfs_qm_dqdestroy(mutex_destroy (&dqp->q_qlock);kmem_zone_free (xfs_Gqm->qm_dqzone, dqp); -atomic_dec (&xfs_Gqm->qm_totaldquots); +XFS_STATS_DEC (xs_qm_dquot); }/*
@@ -516,7 +516,7 @@ xfs_qm_dqread(if (!(type &XFS_DQ_USER ))lockdep_set_class (&dqp->q_qlock, &xfs_dquot_other_class); -atomic_inc (&xfs_Gqm->qm_totaldquots); +XFS_STATS_INC (xs_qm_dquot);trace_xfs_dqread (dqp);
@@ -712,12 +712,12 @@ restart:*/ switch (xfs_qm_dqlookup (mp, id, h, O_dqpp)) {case -1 : -XQM_STATS_INC (xqmstats.xs_qm_dquot_dups); +XFS_STATS_INC (xs_qm_dquot_dups);mutex_unlock (&h->qh_lock);delay (1 ); goto restart;case 0 : -XQM_STATS_INC (xqmstats.xs_qm_dqcachehits); +XFS_STATS_INC (xs_qm_dqcachehits);/* * The dquot was found, moved to the front of the chain, * taken off the freelist if it was on it, and locked
@@ -729,7 +729,7 @@ restart:trace_xfs_dqget_hit (*O_dqpp);return 0 ;/* success */ default : -XQM_STATS_INC (xqmstats.xs_qm_dqcachemisses); +XFS_STATS_INC (xs_qm_dqcachemisses);break ; }
@@ -804,7 +804,7 @@ restart:xfs_qm_dqput (tmpdqp);mutex_unlock (&h->qh_lock);xfs_qm_dqdestroy (dqp); -XQM_STATS_INC (xqmstats.xs_qm_dquot_dups); +XFS_STATS_INC (xs_qm_dquot_dups); goto restart;default :break ;
@@ -873,6 +873,7 @@ recurse:if (list_empty (&dqp->q_freelist)) {list_add_tail (&dqp->q_freelist, &xfs_Gqm->qm_dqfrlist); xfs_Gqm->qm_dqfrlist_cnt++; +XFS_STATS_INC (xs_qm_dquot_unused); }mutex_unlock (&xfs_Gqm->qm_dqfrlist_lock);
@@ -1189,6 +1190,7 @@ xfs_qm_dqpurge(ASSERT (!list_empty (&dqp->q_freelist));list_del_init (&dqp->q_freelist); xfs_Gqm->qm_dqfrlist_cnt--; +XFS_STATS_DEC (xs_qm_dquot_unused);mutex_unlock (&xfs_Gqm->qm_dqfrlist_lock);xfs_qm_dqdestroy (dqp);
fs/xfs/xfs_qm.c +5 -4
@@ -134,7 +134,6 @@ xfs_Gqm_init(void) }else xqm->qm_dqtrxzone = qm_dqtrxzone; -atomic_set (&xqm->qm_totaldquots,0 ); xqm->qm_nrefs =0 ;return xqm;
@@ -1637,10 +1636,11 @@ xfs_qm_dqreclaim_one(xfs_dqunlock (dqp);trace_xfs_dqreclaim_want (dqp); -XQM_STATS_INC (xqmstats.xs_qm_dqwants); +XFS_STATS_INC (xs_qm_dqwants);list_del_init (&dqp->q_freelist); xfs_Gqm->qm_dqfrlist_cnt--; +XFS_STATS_DEC (xs_qm_dquot_unused);return ; }
@@ -1690,9 +1690,10 @@ xfs_qm_dqreclaim_one(ASSERT (dqp->q_nrefs ==0 );list_move_tail (&dqp->q_freelist, dispose_list); xfs_Gqm->qm_dqfrlist_cnt--; +XFS_STATS_DEC (xs_qm_dquot_unused);trace_xfs_dqreclaim_done (dqp); -XQM_STATS_INC (xqmstats.xs_qm_dqreclaims); +XFS_STATS_INC (xs_qm_dqreclaims);return ; out_busy:
@@ -1704,7 +1705,7 @@ out_busy:list_move_tail (&dqp->q_freelist, &xfs_Gqm->qm_dqfrlist);trace_xfs_dqreclaim_busy (dqp); -XQM_STATS_INC (xqmstats.xs_qm_dqreclaim_misses); +XFS_STATS_INC (xs_qm_dqreclaim_misses); }STATIC int
fs/xfs/xfs_qm_stats.c deleted +0 -105
105 lines not on this page · raw message
fs/xfs/xfs_qm_stats.h deleted +0 -53
53 lines not on this page · raw message
fs/xfs/xfs_stats.h +10 -0
@@ -183,6 +183,16 @@ struct xfsstats {__uint32_t xs_ibt_2_alloc;__uint32_t xs_ibt_2_free;__uint32_t xs_ibt_2_moves; +#define XFSSTAT_END_XQMSTAT (XFSSTAT_END_IBT_V2+6) +__uint32_t xs_qm_dqreclaims; +__uint32_t xs_qm_dqreclaim_misses; +__uint32_t xs_qm_dquot_dups; +__uint32_t xs_qm_dqcachemisses; +__uint32_t xs_qm_dqcachehits; +__uint32_t xs_qm_dqwants; +#define XFSSTAT_END_QM (XFSSTAT_END_XQMSTAT+2) +__uint32_t xs_qm_dquot; +__uint32_t xs_qm_dquot_unused;/* Extra precision counters */ __uint64_t xs_xstrat_bytes;__uint64_t xs_write_bytes;
fs/xfs/xfs_qm.h +0 -2
@@ -21,7 +21,6 @@#include "xfs_dquot_item.h" #include "xfs_dquot.h" #include "xfs_quota_priv.h" -#include "xfs_qm_stats.h" struct xfs_qm ;struct xfs_inode ;
@@ -60,7 +59,6 @@ typedef struct xfs_qm {struct list_head qm_dqfrlist;/* freelist of dquots */ struct mutex qm_dqfrlist_lock;int qm_dqfrlist_cnt; -atomic_t qm_totaldquots;/* total incore dquots */ uint qm_nrefs;/* file systems with quota on */ kmem_zone_t *qm_dqzone;/* dquot mem-alloc zone */ kmem_zone_t *qm_dqtrxzone;/* t_dqinfo of transactions */
fs/xfs/xfs_qm_bhv.c +0 -2
@@ -92,13 +92,11 @@ xfs_qm_init(void) {printk (KERN_INFO "SGI XFS Quota Management subsystem\n" );mutex_init (&xfs_Gqm_lock); -xfs_qm_init_procfs (); } void __exitxfs_qm_exit (void ) { -xfs_qm_cleanup_procfs ();if (qm_dqzone)kmem_zone_destroy (qm_dqzone);if (qm_dqtrxzone)
fs/xfs/xfs_stats.c +87 -12
138 lines not on this page · raw message
fs/xfs/Makefile +0 -3
@@ -96,9 +96,6 @@ xfs-$(CONFIG_XFS_QUOTA) += xfs_dquot.o xfs_qm_bhv.o \ xfs_qm.o \ xfs_quotaops.o -ifeq ($(CONFIG_XFS_QUOTA),y) -xfs-$(CONFIG_PROC_FS) += xfs_qm_stats.o -endif xfs-$(CONFIG_XFS_RT) += xfs_rtalloc.o xfs-$(CONFIG_XFS_POSIX_ACL) += xfs_acl.o xfs-$(CONFIG_PROC_FS) += xfs_stats.o
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 4/8 v2] xfs: use common code for quota statistics
Quoted 6 lines · Christoph Hellwig
Switch the quota code over to use the generic XFS statistics infrastructure. While the legacy
/proc/fs/xfs/xqmand/proc/fs/xfs/xqmstatsinterfaces are preserved for now the statistics that still have a meaning with the current code are now also available from/proc/fs/xfs/stats.Signed-off-by Christoph Hellwig <[email protected]>
Looks fine to me.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 4/8 v2] xfs: use common code for quota statistics
In reply to Christoph HellwigQuoted 6 lines · Christoph Hellwig
Switch the quota code over to use the generic XFS statistics infrastructure. While the legacy
/proc/fs/xfs/xqmand/proc/fs/xfs/xqmstatsinterfaces are preserved for now the statistics that still have a meaning with the current code are now also available from/proc/fs/xfs/stats.Signed-off-by Christoph Hellwig <[email protected]>
...
fs/xfs/xfs_stats.c static const struct file_operations xfs_ · line 112
Quoted 8 lines
fs/xfs/xfs_stats.c +8
-0+/* legacy quota interfaces */ +#ifdef CONFIG_XFS_QUOTA +static int xqm_proc_show (struct seq_file *m,void *v) +{ +/* maximum; incore; ratio free to inuse; freelist */ + seq_printf(m, "%d\t%d\t%d\t%u\n", + 0, + counter_val(XFSSTAT_END_XQMSTAT),
That's xfs_qm_dquot
Review
Quoted 2 lines
(quoted diff) +2
-0+ 0, + counter_val(XFSSTAT_END_XQMSTAT + 1));
and xfs_qm_dquot_unused? A comment would make your intent clear.
Quoted 14 lines
fs/xfs/xfs_stats.c +14
-0+return 0 ; +} + +static int xqm_proc_open (struct inode *inode,struct file *file) +{ +return single_open (file, xqm_proc_show,NULL ); +} + +static const struct file_operations xqm_proc_fops = { + .owner =THIS_MODULE , + .open = xqm_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release,
fs/xfs/xfs_stats.c static const struct file_operations xfs_ · line 138
Quoted 10 lines
fs/xfs/xfs_stats.c +10
-0+}; + +/* legacy quota stats interface no 2 */ +static int xqmstat_proc_show (struct seq_file *m,void *v) +{ +int j; + +seq_printf (m,"qm" ); +for (j =XFSSTAT_END_IBT_V2 ; j <XFSSTAT_END_XQMSTAT ; j++) +seq_printf (m," %u" ,counter_val (j));
And a comment here with all of the stuff you're printing out would be total overkill. Nevermind. ;)
...
Quoted 17 lines
int
xfs_init_procfs(void)
{fs/xfs/xfs_stats.c +9
-1@@ -105,10 +162,24 @@ xfs_init_procfs(void)if (!proc_create ("fs/xfs/stat" ,0 ,NULL , &xfs_stat_proc_fops)) - goto out_remove_entry; + goto out_remove_xfs_dir; +#ifdef CONFIG_XFS_QUOTA +if (!proc_create ("fs/xfs/xqmstat" ,0 ,NULL , + &xqmstat_proc_fops)) + goto out_remove_stat_file; +if (!proc_create ("fs/xfs/xqm" ,0 ,NULL , + &xqm_proc_fops)) + goto out_remove_xqmstat_file; +#endif
fs/xfs/xfs_stats.c xfs_init_procfs(void) · line 182
Quoted 10 lines
fs/xfs/xfs_stats.c +7
-1return 0 ; - out_remove_entry: +#ifdef CONFIG_XFS_QUOTA + out_remove_xqmstat_file: +remove_proc_entry ("fs/xfs/xqmstat" ,NULL ); + out_remove_stat_file: +remove_proc_entry ("fs/xfs/stat" ,NULL ); +#endif + out_remove_xfs_dir:
I'm glad to see that you added error handling here. There wasn't any in the xfs_qm_init_procfs before.
This patch looks great. It might break some PCP scripts, I'm not sure.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 4/8 v2] xfs: use common code for quota statistics
Quoted 9 lines · Ben Myers
fs/xfs/xfs_stats.c static const struct file_operations xfs_ · line 112
Quoted 6 lines
fs/xfs/xfs_stats.c +6
-0+static int xqm_proc_show (struct seq_file *m,void *v) +{ +/* maximum; incore; ratio free to inuse; freelist */ + seq_printf(m, "%d\t%d\t%d\t%u\n", + 0, + counter_val(XFSSTAT_END_XQMSTAT),That's
xfs_qm_dquot
Quoted 4 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+ 0, + counter_val(XFSSTAT_END_XQMSTAT + 1));and
xfs_qm_dquot_unused? A comment would make your intent clear.
In that case we'd have to comment the existing code, too. And in that case reoding the code to actually make sense would be a good idea as well.
Quoted 1 line
This patch looks great. It might break some PCP scripts, I'm not sure.
Why would it break them? The existing stats are still kept around, and new additions to the main stats file are expected to happen once in a while.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 4/8 v2] xfs: use common code for quota statistics
Quoted 10 lines · Christoph Hellwig
Quoted 8 lines · Ben Myers
fs/xfs/xfs_stats.c static const struct file_operations xfs_ · line 112
Quoted 6 lines
fs/xfs/xfs_stats.c +6
-0+static int xqm_proc_show (struct seq_file *m,void *v) +{ +/* maximum; incore; ratio free to inuse; freelist */ + seq_printf(m, "%d\t%d\t%d\t%u\n", + 0, + counter_val(XFSSTAT_END_XQMSTAT),This patch looks great. It might break some PCP scripts, I'm not sure.
Quoted 3 lines
Why would it break them? The existing stats are still kept around, and new additions to the main stats file are expected to happen once in a while.
I'm not sure that it would. You've added a line to the common stats procfile, and the pmda might expect the xpc line immediately after ibt2.
I've made a note to take a look.
-Ben
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 4/8 v2] xfs: use common code for quota statistics
Quoted 11 lines · Ben Myers
Quoted 10 lines · Christoph Hellwig
Quoted 8 lines · Ben Myers
fs/xfs/xfs_stats.c static const struct file_operations xfs_ · line 112
Quoted 6 lines
fs/xfs/xfs_stats.c +6
-0+static int xqm_proc_show (struct seq_file *m,void *v) +{ +/* maximum; incore; ratio free to inuse; freelist */ + seq_printf(m, "%d\t%d\t%d\t%u\n", + 0, + counter_val(XFSSTAT_END_XQMSTAT),This patch looks great. It might break some PCP scripts, I'm not sure.
Quoted 6 lines
Quoted 3 lines
Why would it break them? The existing stats are still kept around, and new additions to the main stats file are expected to happen once in a while.
I'm not sure that it would. You've added a line to the common stats procfile, and the pmda might expect the xpc line immediately after ibt2.
IIRC the pmda triggers off the descriptor at the start of the line. It ignores lines that it doesn't understand the descriptor for (like all the v2 btree stats). I should probably update the pmda fo all those stats....
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 4/8 v2] xfs: use common code for quota statistics
Hey guys,
Quoted 11 lines · Dave Chinner
Quoted 10 lines · Ben Myers
Quoted 9 lines · Christoph Hellwig
Quoted 8 lines · Ben Myers
fs/xfs/xfs_stats.c static const struct file_operations xfs_ · line 112
Quoted 6 lines
fs/xfs/xfs_stats.c +6
-0+static int xqm_proc_show (struct seq_file *m,void *v) +{ +/* maximum; incore; ratio free to inuse; freelist */ + seq_printf(m, "%d\t%d\t%d\t%u\n", + 0, + counter_val(XFSSTAT_END_XQMSTAT),This patch looks great. It might break some PCP scripts, I'm not
Quoted 9 lines
sure.
Quoted 7 lines
Quoted 4 lines
Why would it break them? The existing stats are still kept around, and new additions to the main stats file are expected to happen once in a while.
I'm not sure that it would. You've added a line to the common stats procfile, and the pmda might expect the xpc line immediately after ibt2.
In an amusing twist, it turns out that the quota stats were originally part of
the main procfs stats file and were later on moved into their own file as part of making xqm modular. So, by good fortune PCP already supports a move back into the original stats file for these stats, provided the same prefix ("qm") is used.
Quoted 3 lines
IIRC the pmda triggers off the descriptor at the start of the line.
That's correct.
Quoted 4 lines
It ignores lines that it doesn't understand the descriptor for (like all the v2 btree stats). I should probably update the pmda fo all those stats....
That was done quite awhile back (mid-2010), unless there's some other stats come along since then that I don't know about yet? (are these the ones you mean, Dave?...)
$ egrep '^[a-z]+2 ' /proc/fs/xfs/stat abtb2 4769967 54332939 635853 643428 507 508 282413 22672 61298 45587 1093 1111 1600 1619 393677507 abtc2 10166604 113971561 4264119 4272402 1213 1214 77487 9464 29584 35760 1551 1571 2764 2785 1438715558 bmbt2 152523 1231148 52950 42558 0 0 1372 1385 5117 1340 85 48 85 48 1545160 ibt2 9475130 102652889 5672 2878 0 0 6549337 15214 801 869 17 0 17 0 1202730 $
( those are the xfs.btree.alloc_blocks.*, xfs.btree.alloc_contig.*, xfs.btree.block_map.*, and xfs.btree.inode.lookup.* metrics )
cheers.
--
Nathan
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 4/8 v2] xfs: use common code for quota statistics
Quoted 19 lines · Nathan Scott
Quoted 4 lines · Dave Chinner
It ignores lines that it doesn't understand the descriptor for (like all the v2 btree stats). I should probably update the pmda fo all those stats....
That was done quite awhile back (mid-2010), unless there's some other stats come along since then that I don't know about yet? (are these the ones you mean, Dave?...)
$ egrep '^[a-z]+2 ' /proc/fs/xfs/stat abtb2 4769967 54332939 635853 643428 507 508 282413 22672 61298 45587 1093 1111 1600 1619 393677507 abtc2 10166604 113971561 4264119 4272402 1213 1214 77487 9464 29584 35760 1551 1571 2764 2785 1438715558 bmbt2 152523 1231148 52950 42558 0 0 1372 1385 5117 1340 85 48 85 48 1545160 ibt2 9475130 102652889 5672 2878 0 0 6549337 15214 801 869 17 0 17 0 1202730 $
Quoted 2 lines
( those are the xfs.btree.alloc_blocks.*, xfs.btree.alloc_contig.*, xfs.btree.block_map.*, and xfs.btree.inode.lookup.* metrics )
Yeah, that's them. I hadn't noticed them in name space because I'd been looking for similar metric names to xfs.bmap_btree rather than in a separate xfs.btree heirarchy.
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
PATCH 5/8 xfs: per-filesystem dquot LRU lists
In reply to Christoph HellwigReplace the global dquot lru lists with a per-filesystem one.
Note that the shrinker isn't wire up to the per-superblock VFS shrinker infrastructure as would have problems summing up and splitting the counts for inodes and dquots. I don't think this is a major problem as the quota cache isn't as interwinded with the inode cache as the dentry cache is, because an inode that is dropped from the cache will generally release a dquot reference, but most of the time it won't be the last one.
--- fs/xfs/xfs_dquot.c | 85 +++++++++++++++++++++++++++-------------------------- fs/xfs/xfs_dquot.h | 2 - fs/xfs/xfs_qm.c | 59 +++++++++++++++--------------------- fs/xfs/xfs_qm.h | 7 ++-- 4 files changed, 74 insertions(+), 79 deletions(-)
fs/xfs/xfs_dquot.c +44 -41
@@ -47,7 +47,7 @@* qi->qi_dqlist_lock * dquot->q_qlock (xfs_dqlock() and friends) * dquot->q_flush (xfs_dqflock() and friends) -* xfs_Gqm->qm_dqfrlist_lock +* qi->qi_lru_lock * * If two dquots need to be locked the order is user before group/project, * otherwise by the lowest id first, see xfs_dqlock2.
@@ -69,7 +69,7 @@ voidxfs_qm_dqdestroy ( xfs_dquot_t *dqp) { -ASSERT (list_empty (&dqp->q_freelist)); +ASSERT (list_empty (&dqp->q_lru));mutex_destroy (&dqp->q_qlock);kmem_zone_free (xfs_Gqm->qm_dqzone, dqp);
@@ -497,7 +497,7 @@ xfs_qm_dqread( dqp->dq_flags = type; dqp->q_core.d_id =cpu_to_be32 (id); dqp->q_mount = mp; -INIT_LIST_HEAD (&dqp->q_freelist); +INIT_LIST_HEAD (&dqp->q_lru);mutex_init (&dqp->q_qlock);init_waitqueue_head (&dqp->q_pinwait);
@@ -844,38 +844,22 @@ restart: } -/* -* Release a reference to the dquot (decrement ref-count) -* and unlock it. If there is a group quota attached to this -* dquot, carefully release that too without tripping over -* deadlocks'n'stuff. -*/ -void -xfs_qm_dqput ( +STATIC void +xfs_qm_dqput_final (struct xfs_dquot *dqp) { +struct xfs_quotainfo *qi = dqp->q_mount->m_quotainfo;struct xfs_dquot *gdqp; -ASSERT (dqp->q_nrefs >0 ); -ASSERT (XFS_DQ_IS_LOCKED (dqp)); - -trace_xfs_dqput (dqp); - -recurse: -if (--dqp->q_nrefs >0 ) { -xfs_dqunlock (dqp); -return ; - } -trace_xfs_dqput_free (dqp); -mutex_lock (&xfs_Gqm->qm_dqfrlist_lock); -if (list_empty (&dqp->q_freelist)) { -list_add_tail (&dqp->q_freelist, &xfs_Gqm->qm_dqfrlist); - xfs_Gqm->qm_dqfrlist_cnt++; +mutex_lock (&qi->qi_lru_lock); +if (list_empty (&dqp->q_lru)) { +list_add_tail (&dqp->q_lru, &qi->qi_lru_list); + qi->qi_lru_count++;XFS_STATS_INC (xs_qm_dquot_unused); } -mutex_unlock (&xfs_Gqm->qm_dqfrlist_lock); +mutex_unlock (&qi->qi_lru_lock);/* * If we just added a udquot to the freelist, then we want to release
@@ -892,10 +876,29 @@ recurse:/* * If we had a group quota hint, release it now. */ -if (gdqp) { - dqp = gdqp; - goto recurse; - } +if (gdqp) +xfs_qm_dqput (gdqp); +} + +/* +* Release a reference to the dquot (decrement ref-count) and unlock it. +* +* If there is a group quota attached to this dquot, carefully release that +* too without tripping over deadlocks'n'stuff. +*/ +void +xfs_qm_dqput ( +struct xfs_dquot *dqp) +{ +ASSERT (dqp->q_nrefs >0 ); +ASSERT (XFS_DQ_IS_LOCKED (dqp)); + +trace_xfs_dqput (dqp); + +if (--dqp->q_nrefs >0 ) +xfs_dqunlock (dqp); +else +xfs_qm_dqput_final (dqp); }/*
@@ -1126,6 +1129,7 @@ xfs_qm_dqpurge( {struct xfs_mount *mp = dqp->q_mount;struct xfs_dqhash *qh = dqp->q_hash; +struct xfs_quotainfo *qi = mp->m_quotainfo;xfs_dqlock (dqp);
@@ -1176,22 +1180,21 @@ xfs_qm_dqpurge( qh->qh_version++;mutex_unlock (&qh->qh_lock); -mutex_lock (&mp->m_quotainfo->qi_dqlist_lock); +mutex_lock (&qi->qi_dqlist_lock);list_del_init (&dqp->q_mplist); - mp->m_quotainfo->qi_dqreclaims++; - mp->m_quotainfo->qi_dquots--; -mutex_unlock (&mp->m_quotainfo->qi_dqlist_lock); + qi->qi_dqreclaims++; + qi->qi_dquots--; +mutex_unlock (&qi->qi_dqlist_lock);/* * We move dquots to the freelist as soon as their reference count * hits zero, so it really should be on the freelist here. */ -mutex_lock (&xfs_Gqm->qm_dqfrlist_lock); -ASSERT (!list_empty (&dqp->q_freelist)); -list_del_init (&dqp->q_freelist); - xfs_Gqm->qm_dqfrlist_cnt--; -XFS_STATS_DEC (xs_qm_dquot_unused); -mutex_unlock (&xfs_Gqm->qm_dqfrlist_lock); +mutex_lock (&qi->qi_lru_lock); +ASSERT (!list_empty (&dqp->q_lru)); +list_del_init (&dqp->q_lru); + qi->qi_lru_count--; +mutex_unlock (&qi->qi_lru_lock);xfs_qm_dqdestroy (dqp); }
fs/xfs/xfs_dquot.h +1 -1
@@ -47,7 +47,7 @@ struct xfs_trans;*/ typedef struct xfs_dquot { uint dq_flags; /* various flags (XFS_DQ_*) */ - struct list_head q_freelist; /* global free list of dquots */ + struct list_head q_lru; /* global free list of dquots */ struct list_head q_mplist; /* mount's list of dquots */ struct list_head q_hashlist; /* gloabl hash list of dquots */ xfs_dqhash_t *q_hash; /* the hashchain header */
fs/xfs/xfs_qm.c +25 -34
146 lines not on this page · raw message
fs/xfs/xfs_qm.h +4 -3
@@ -56,9 +56,6 @@ typedef struct xfs_qm {xfs_dqlist_t *qm_usr_dqhtable;/* udquot hash table */ xfs_dqlist_t *qm_grp_dqhtable;/* gdquot hash table */ uint qm_dqhashmask;/* # buckets in dq hashtab - 1 */ -struct list_head qm_dqfrlist;/* freelist of dquots */ -struct mutex qm_dqfrlist_lock; -int qm_dqfrlist_cnt;uint qm_nrefs;/* file systems with quota on */ kmem_zone_t *qm_dqzone;/* dquot mem-alloc zone */ kmem_zone_t *qm_dqtrxzone;/* t_dqinfo of transactions */
@@ -71,6 +68,9 @@ typedef struct xfs_qm { typedef struct xfs_quotainfo { xfs_inode_t *qi_uquotaip; /* user quota inode */ xfs_inode_t *qi_gquotaip; /* group quota inode */ + struct list_head qi_lru_list; + struct mutex qi_lru_lock; + int qi_lru_count; struct list_head qi_dqlist; /* all dquots in filesys */ struct mutex qi_dqlist_lock; int qi_dquots;
@@ -91,6 +91,7 @@ typedef struct xfs_quotainfo {xfs_qcnt_t qi_isoftlimit;/* default inode count soft limit */ xfs_qcnt_t qi_rtbhardlimit;/* default realtime blk hard limit */ xfs_qcnt_t qi_rtbsoftlimit;/* default realtime blk soft limit */ +struct shrinker qi_shrinker; } xfs_quotainfo_t;
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 5/8] xfs: per-filesystem dquot LRU lists
Quoted 10 lines · Christoph Hellwig
Replace the global dquot lru lists with a per-filesystem one.
Note that the shrinker isn't wire up to the per-superblock VFS shrinker infrastructure as would have problems summing up and splitting the counts for inodes and dquots. I don't think this is a major problem as the quota cache isn't as interwinded with the inode cache as the dentry cache is, because an inode that is dropped from the cache will generally release a dquot reference, but most of the time it won't be the last one.
Signed-off-by Christoph Hellwig <[email protected]>
Looks OK.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 5/8] xfs: per-filesystem dquot LRU lists
In reply to Christoph HellwigQuoted 11 lines · Christoph Hellwig
Replace the global dquot lru lists with a per-filesystem one.
Note that the shrinker isn't wire up to the per-superblock VFS shrinker infrastructure as would have problems summing up and splitting the counts for inodes and dquots. I don't think this is a major problem as the quota cache isn't as interwinded with the inode cache as the dentry cache is, because an inode that is dropped from the cache will generally release a dquot reference, but most of the time it won't be the last one.
Signed-off-by Christoph Hellwig <[email protected]>
...
Quoted 21 lines
fs/xfs/xfs_dquot.c +5
-4@@ -1126,6 +1129,7 @@ xfs_qm_dqpurge( {struct xfs_mount *mp = dqp->q_mount;struct xfs_dqhash *qh = dqp->q_hash; +struct xfs_quotainfo *qi = mp->m_quotainfo;xfs_dqlock (dqp);@@ -1176,22 +1180,21 @@ xfs_qm_dqpurge( qh->qh_version++;mutex_unlock (&qh->qh_lock); -mutex_lock (&mp->m_quotainfo->qi_dqlist_lock); +mutex_lock (&qi->qi_dqlist_lock);list_del_init (&dqp->q_mplist); - mp->m_quotainfo->qi_dqreclaims++; - mp->m_quotainfo->qi_dquots--; -mutex_unlock (&mp->m_quotainfo->qi_dqlist_lock); + qi->qi_dqreclaims++; + qi->qi_dquots--; +mutex_unlock (&qi->qi_dqlist_lock);
fs/xfs/xfs_dquot.c xfs_qm_dqpurge( · line 1193
Quoted 10 lines
fs/xfs/xfs_dquot.c +0
-5/* * We move dquots to the freelist as soon as their reference count * hits zero, so it really should be on the freelist here. */ -mutex_lock (&xfs_Gqm->qm_dqfrlist_lock); -ASSERT (!list_empty (&dqp->q_freelist)); -list_del_init (&dqp->q_freelist); - xfs_Gqm->qm_dqfrlist_cnt--; -XFS_STATS_DEC (xs_qm_dquot_unused);
Looks like you have removed this decrement of xs_qm_dquot_unused. You didn't mention it in your commit message, so I am not sure if it is intentional.
Other than that, this patch looks good.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
PATCH 6/8 xfs: use per-filesystem radix trees for dquot lookup
In reply to Christoph HellwigReplace the global hash tables for looking up in-memory dquot structures with per-filesystem radix trees to allow scaling to a large number of in-memory dquot structures.
--- fs/xfs/xfs_dquot.c | 188 ++++++++++++------------------------------------ fs/xfs/xfs_dquot.h | 12 --- fs/xfs/xfs_qm.c | 95 ++---------------------- fs/xfs/xfs_qm.h | 19 ++-- fs/xfs/xfs_quota_priv.h | 11 -- fs/xfs/xfs_trace.h | 4 - 6 files changed, 66 insertions(+), 263 deletions(-)
fs/xfs/xfs_qm.c +8 -87
@@ -54,9 +54,6 @@ struct xfs_qm *xfs_Gqm;kmem_zone_t *qm_dqzone;kmem_zone_t *qm_dqtrxzone; -STATIC void xfs_qm_list_init(xfs_dqlist_t *, char *, int); -STATIC void xfs_qm_list_destroy(xfs_dqlist_t *); - STATIC int xfs_qm_init_quotainos(xfs_mount_t *); STATIC int xfs_qm_init_quotainfo(xfs_mount_t *); STATIC int xfs_qm_shake(struct shrinker *, struct shrink_control *);
@@ -68,37 +65,9 @@ STATIC int xfs_qm_shake(struct shrinker STATIC struct xfs_qm *xfs_Gqm_init (void ) { -xfs_dqhash_t *udqhash, *gdqhash;xfs_qm_t *xqm; -size_t hsize; -uint i; - -/* -* Initialize the dquot hash tables. -*/ - udqhash =kmem_zalloc_greedy (&hsize, -XFS_QM_HASHSIZE_LOW *sizeof (xfs_dqhash_t), -XFS_QM_HASHSIZE_HIGH *sizeof (xfs_dqhash_t)); -if (!udqhash) - goto out; - - gdqhash =kmem_zalloc_large (hsize); -if (!gdqhash) - goto out_free_udqhash; - - hsize /=sizeof (xfs_dqhash_t); xqm =kmem_zalloc (sizeof (xfs_qm_t),KM_SLEEP ); - xqm->qm_dqhashmask = hsize -1 ; - xqm->qm_usr_dqhtable = udqhash; - xqm->qm_grp_dqhtable = gdqhash; -ASSERT (xqm->qm_usr_dqhtable !=NULL ); -ASSERT (xqm->qm_grp_dqhtable !=NULL ); - -for (i =0 ; i < hsize; i++) { -xfs_qm_list_init (&(xqm->qm_usr_dqhtable[i]),"uxdqh" , i); -xfs_qm_list_init (&(xqm->qm_grp_dqhtable[i]),"gxdqh" , i); - }/* * dquot zone. we register our own low-memory callback.
@@ -122,11 +91,6 @@ xfs_Gqm_init(void) xqm->qm_nrefs =0 ;return xqm; - - out_free_udqhash: -kmem_free_large (udqhash); - out: -return NULL ; }/*
@@ -136,22 +100,9 @@ STATIC voidxfs_qm_destroy ( struct xfs_qm *xqm) { -int hsize, i; -ASSERT (xqm !=NULL );ASSERT (xqm->qm_nrefs ==0 ); - hsize = xqm->qm_dqhashmask +1 ; -for (i =0 ; i < hsize; i++) { -xfs_qm_list_destroy (&(xqm->qm_usr_dqhtable[i])); -xfs_qm_list_destroy (&(xqm->qm_grp_dqhtable[i])); - } -kmem_free_large (xqm->qm_usr_dqhtable); -kmem_free_large (xqm->qm_grp_dqhtable); - xqm->qm_usr_dqhtable =NULL ; - xqm->qm_grp_dqhtable =NULL ; - xqm->qm_dqhashmask =0 ; -kmem_free (xqm); }
@@ -762,14 +713,6 @@ xfs_qm_dqdetach( }/* -* The hash chains and the mplist use the same xfs_dqhash structure as -* their list head, but we can take the mplist qh_lock and one of the -* hash qh_locks at the same time without any problem as they aren't -* related. -*/ -static struct lock_class_key xfs_quota_mplist_class; - -/* * This initializes all the quota information that's kept in the * mount structure */
@@ -802,9 +745,12 @@ xfs_qm_init_quotainfo(return error; } +INIT_RADIX_TREE (&qinf->qi_uquota_tree,GFP_NOFS ); +INIT_RADIX_TREE (&qinf->qi_gquota_tree,GFP_NOFS ); +mutex_init (&qinf->qi_tree_lock); +INIT_LIST_HEAD (&qinf->qi_dqlist);mutex_init (&qinf->qi_dqlist_lock); -lockdep_set_class (&qinf->qi_dqlist_lock, &xfs_quota_mplist_class);INIT_LIST_HEAD (&qinf->qi_lru_list); qinf->qi_lru_count =0 ;
@@ -924,30 +870,6 @@ xfs_qm_destroy_quotainfo( mp->m_quotainfo =NULL ; } - - -/* ------------------- PRIVATE STATIC FUNCTIONS ----------------------- */ - -/* ARGSUSED */ -STATIC void -xfs_qm_list_init ( -xfs_dqlist_t *list, -char *str, -int n) -{ -mutex_init (&list->qh_lock); -INIT_LIST_HEAD (&list->qh_list); - list->qh_version =0 ; - list->qh_nelems =0 ; -} - -STATIC void -xfs_qm_list_destroy ( -xfs_dqlist_t *list) -{ -mutex_destroy (&(list->qh_lock)); -} -/* * Create an inode and return with a reference already taken, but unlocked * This is how we create quota inodes
@@ -1592,10 +1514,10 @@ xfs_qm_dqfree_one(struct xfs_mount *mp = dqp->q_mount;struct xfs_quotainfo *qi = mp->m_quotainfo; -mutex_lock (&dqp->q_hash->qh_lock); -list_del_init (&dqp->q_hashlist); - dqp->q_hash->qh_version++; -mutex_unlock (&dqp->q_hash->qh_lock); +mutex_lock (&qi->qi_tree_lock); +radix_tree_delete (XFS_DQUOT_TREE (qi, dqp->q_core.d_flags), +be32_to_cpu (dqp->q_core.d_id)); +mutex_unlock (&qi->qi_tree_lock);mutex_lock (&qi->qi_dqlist_lock);list_del_init (&dqp->q_mplist);
@@ -1634,7 +1556,6 @@ xfs_qm_dqreclaim_one(return ; } -ASSERT (dqp->q_hash);ASSERT (!list_empty (&dqp->q_mplist));/*
fs/xfs/xfs_qm.h +8 -11
@@ -31,12 +31,6 @@ extern kmem_zone_t *qm_dqzone;extern kmem_zone_t *qm_dqtrxzone;/* -* Dquot hashtable constants/threshold values. -*/ -#define XFS_QM_HASHSIZE_LOW (PAGE_SIZE / sizeof(xfs_dqhash_t)) -#define XFS_QM_HASHSIZE_HIGH ((PAGE_SIZE * 4) / sizeof(xfs_dqhash_t)) - -/* * This defines the unit of allocation of dquots. * Currently, it is just one file system block, and a 4K blk contains 30 * (136 * 30 = 4080) dquots. It's probably not worth trying to make
@@ -47,15 +41,10 @@ extern kmem_zone_t *qm_dqtrxzone;*/ #define XFS_DQUOT_CLUSTER_SIZE_FSB (xfs_filblks_t)1 -typedef xfs_dqhash_t xfs_dqlist_t ; -/* * Quota Manager (global) structure. Lives only in core. */ typedef struct xfs_qm { - xfs_dqlist_t *qm_usr_dqhtable;/* udquot hash table */ - xfs_dqlist_t *qm_grp_dqhtable;/* gdquot hash table */ - uint qm_dqhashmask; /* # buckets in dq hashtab - 1 */ uint qm_nrefs; /* file systems with quota on */ kmem_zone_t *qm_dqzone; /* dquot mem-alloc zone */ kmem_zone_t *qm_dqtrxzone; /* t_dqinfo of transactions */
@@ -66,6 +55,9 @@ typedef struct xfs_qm {* The mount structure keeps a pointer to this. */ typedef struct xfs_quotainfo { + struct radix_tree_root qi_uquota_tree; + struct radix_tree_root qi_gquota_tree; + struct mutex qi_tree_lock; xfs_inode_t *qi_uquotaip; /* user quota inode */ xfs_inode_t *qi_gquotaip; /* group quota inode */ struct list_head qi_lru_list;
@@ -94,6 +86,11 @@ typedef struct xfs_quotainfo {struct shrinker qi_shrinker; } xfs_quotainfo_t; +#define XFS_DQUOT_TREE (qi, type) \ + ((type & XFS_DQ_USER) ? \ + &((qi)->qi_uquota_tree) : \ + &((qi)->qi_gquota_tree)) +extern void xfs_trans_mod_dquot (xfs_trans_t *,xfs_dquot_t *,uint ,long ); extern int xfs_trans_reserve_quota_bydquots(xfs_trans_t *, xfs_mount_t *,
fs/xfs/xfs_dquot.c +48 -140
271 lines not on this page · raw message
fs/xfs/xfs_dquot.h +0 -12
@@ -29,16 +29,6 @@* when quotas are off. */ -/* -* The hash chain headers (hash buckets) -*/ -typedef struct xfs_dqhash { -struct list_head qh_list; -struct mutex qh_lock; -uint qh_version;/* ever increasing version */ -uint qh_nelems;/* number of dquots on the list */ -}xfs_dqhash_t ; -struct xfs_mount ;struct xfs_trans ;
@@ -49,8 +39,6 @@ typedef struct xfs_dquot {uint dq_flags;/* various flags (XFS_DQ_*) */ struct list_head q_lru;/* global free list of dquots */ struct list_head q_mplist;/* mount's list of dquots */ -struct list_head q_hashlist;/* gloabl hash list of dquots */ -xfs_dqhash_t *q_hash;/* the hashchain header */ struct xfs_mount *q_mount;/* filesystem this relates to */ struct xfs_trans *q_transp;/* trans this belongs to currently */ uint q_nrefs;/* # active refs from inodes */
fs/xfs/xfs_quota_priv.h +0 -11
@@ -24,17 +24,6 @@*/ #define XFS_DQITER_MAP_SIZE 10 -/* -* Hash into a bucket in the dquot hash table, based on <mp, id>. -*/ -#define XFS_DQ_HASHVAL (mp, id) (((__psunsigned_t)(mp) + \ - (__psunsigned_t)(id)) & \ - (xfs_Gqm->qm_dqhashmask - 1)) -#define XFS_DQ_HASH (mp, id, type) (type == XFS_DQ_USER ? \ - (xfs_Gqm->qm_usr_dqhtable + \ - XFS_DQ_HASHVAL(mp, id)) : \ - (xfs_Gqm->qm_grp_dqhtable + \ - XFS_DQ_HASHVAL(mp, id)))#define XFS_IS_DQUOT_UNINITIALIZED (dqp) ( \ !dqp->q_core.d_blk_hardlimit && \ !dqp->q_core.d_blk_softlimit && \
fs/xfs/xfs_trace.h +2 -2
@@ -741,10 +741,10 @@ DEFINE_DQUOT_EVENT(xfs_dqalloc);DEFINE_DQUOT_EVENT (xfs_dqtobp_read);DEFINE_DQUOT_EVENT (xfs_dqread);DEFINE_DQUOT_EVENT (xfs_dqread_fail); -DEFINE_DQUOT_EVENT (xfs_dqlookup_found); -DEFINE_DQUOT_EVENT (xfs_dqlookup_done);DEFINE_DQUOT_EVENT (xfs_dqget_hit);DEFINE_DQUOT_EVENT (xfs_dqget_miss); +DEFINE_DQUOT_EVENT (xfs_dqget_freeing); +DEFINE_DQUOT_EVENT (xfs_dqget_dup);DEFINE_DQUOT_EVENT (xfs_dqput);DEFINE_DQUOT_EVENT (xfs_dqput_wait);DEFINE_DQUOT_EVENT (xfs_dqput_free);
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
PATCH 7/8 xfs: remove the per-filesystem list of dquots
In reply to Christoph HellwigInstead of keeping a separate per-filesystem list of dquots we can walk the radix tree for the two places where we need to iterate all quota structures.
--- fs/xfs/xfs_dquot.c | 37 ++---- fs/xfs/xfs_dquot.h | 3 fs/xfs/xfs_qm.c | 283 +++++++++++++++++++++++------------------------------ fs/xfs/xfs_qm.h | 4 4 files changed, 142 insertions(+), 185 deletions(-)
fs/xfs/xfs_dquot.c +3 -91
@@ -44,10 +44,9 @@* * ip->i_lock * qi->qi_tree_lock -* qi->qi_dqlist_lock -* dquot->q_qlock (xfs_dqlock() and friends) -* dquot->q_flush (xfs_dqflock() and friends) -* qi->qi_lru_lock +* dquot->q_qlock (xfs_dqlock() and friends) +* dquot->q_flush (xfs_dqflock() and friends) +* qi->qi_lru_lock * * If two dquots need to be locked the order is user before group/project, * otherwise by the lowest id first, see xfs_dqlock2.
@@ -729,20 +728,12 @@ restart: }/* -* Attach this dquot to this filesystem's list of all dquots, -* kept inside the mount structure in m_quotainfo field -*/ -mutex_lock (&qi->qi_dqlist_lock); - -/* * We return a locked dquot to the caller, with a reference taken */ xfs_dqlock (dqp); dqp->q_nrefs =1 ; -list_add (&dqp->q_mplist, &qi->qi_dqlist); qi->qi_dquots++; -mutex_unlock (&qi->qi_dqlist_lock);mutex_unlock (&qi->qi_tree_lock); dqret:
@@ -1029,85 +1020,6 @@ xfs_dqlock2( }/* -* Take a dquot out of the mount's dqlist as well as the hashlist. This is -* called via unmount as well as quotaoff, and the purge will always succeed. -*/ -void -xfs_qm_dqpurge ( -struct xfs_dquot *dqp) -{ -struct xfs_mount *mp = dqp->q_mount; -struct xfs_quotainfo *qi = mp->m_quotainfo; - -xfs_dqlock (dqp); - -/* -* If we're turning off quotas, we have to make sure that, for -* example, we don't delete quota disk blocks while dquots are -* in the process of getting written to those disk blocks. -* This dquot might well be on AIL, and we can't leave it there -* if we're turning off quotas. Basically, we need this flush -* lock, and are willing to block on it. -*/ -if (!xfs_dqflock_nowait (dqp)) { -/* -* Block on the flush lock after nudging dquot buffer, -* if it is incore. -*/ -xfs_dqflock_pushbuf_wait (dqp); - } - -/* -* If we are turning this type of quotas off, we don't care -* about the dirty metadata sitting in this dquot. OTOH, if -* we're unmounting, we do care, so we flush it and wait. -*/ -if (XFS_DQ_IS_DIRTY (dqp)) { -int error; - -/* -* We don't care about getting disk errors here. We need -* to purge this dquot anyway, so we go ahead regardless. -*/ - error =xfs_qm_dqflush (dqp,SYNC_WAIT ); -if (error) -xfs_warn (mp,"%s: dquot %p flush failed" , - __func__, dqp); -xfs_dqflock (dqp); - } - -ASSERT (atomic_read (&dqp->q_pincount) ==0 ); -ASSERT (XFS_FORCED_SHUTDOWN (mp) || - !(dqp->q_logitem.qli_item.li_flags &XFS_LI_IN_AIL )); - -xfs_dqfunlock (dqp); -xfs_dqunlock (dqp); - -mutex_lock (&qi->qi_tree_lock); -radix_tree_delete (XFS_DQUOT_TREE (qi, dqp->q_core.d_flags), -be32_to_cpu (dqp->q_core.d_id)); -mutex_unlock (&qi->qi_tree_lock); - -mutex_lock (&qi->qi_dqlist_lock); -list_del_init (&dqp->q_mplist); - qi->qi_dqreclaims++; - qi->qi_dquots--; -mutex_unlock (&qi->qi_dqlist_lock); - -/* -* We move dquots to the freelist as soon as their reference count -* hits zero, so it really should be on the freelist here. -*/ -mutex_lock (&qi->qi_lru_lock); -ASSERT (!list_empty (&dqp->q_lru)); -list_del_init (&dqp->q_lru); - qi->qi_lru_count--; -mutex_unlock (&qi->qi_lru_lock); - -xfs_qm_dqdestroy (dqp); -} - -/* * Give the buffer a little push if it is incore and * wait on the flush lock. */
fs/xfs/xfs_qm.c +229 -196
492 lines not on this page · raw message
fs/xfs/xfs_qm.h +0 -4
@@ -63,11 +63,7 @@ typedef struct xfs_quotainfo {struct list_head qi_lru_list;struct mutex qi_lru_lock;int qi_lru_count; -struct list_head qi_dqlist;/* all dquots in filesys */ -struct mutex qi_dqlist_lock;int qi_dquots; -int qi_dqreclaims;/* a change here indicates -a removal in the dqlist */ time_t qi_btimelimit;/* limit for blks timer */ time_t qi_itimelimit;/* limit for inodes timer */ time_t qi_rtbtimelimit;/* limit for rt blks timer */
fs/xfs/xfs_dquot.h +0 -2
@@ -38,7 +38,6 @@ struct xfs_trans; typedef struct xfs_dquot { uint dq_flags; /* various flags (XFS_DQ_*) */ struct list_head q_lru; /* global free list of dquots */ - struct list_head q_mplist; /* mount's list of dquots */ struct xfs_mount*q_mount; /* filesystem this relates to */ struct xfs_trans*q_transp; /* trans this belongs to currently */ uint q_nrefs; /* # active refs from inodes */
@@ -143,7 +142,6 @@ extern int xfs_qm_dqread(struct xfs_mou uint, struct xfs_dquot **);extern void xfs_qm_dqdestroy (xfs_dquot_t *);extern int xfs_qm_dqflush (xfs_dquot_t *,uint ); -extern void xfs_qm_dqpurge (xfs_dquot_t *);extern void xfs_qm_dqunpin_wait (xfs_dquot_t *);extern void xfs_qm_adjust_dqtimers (xfs_mount_t *,xfs_disk_dquot_t *);
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 7/8] xfs: remove the per-filesystem list of dquots
Quoted 5 lines · Christoph Hellwig
Instead of keeping a separate per-filesystem list of dquots we can walk the radix tree for the two places where we need to iterate all quota structures.
Signed-off-by Christoph Hellwig <[email protected]>
Still a bit of a lookup vs iterate hold-off remaining, but I think we can live with the reduction now. If it proves to be a noticable problem then we can look towards RCU based lookups, I think. Otherwise it looks OK to me.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 7/8] xfs: remove the per-filesystem list of dquots
Quoted 11 lines · Dave Chinner
Quoted 5 lines · Christoph Hellwig
Instead of keeping a separate per-filesystem list of dquots we can walk the radix tree for the two places where we need to iterate all quota structures.
Signed-off-by Christoph Hellwig <[email protected]>Still a bit of a lookup vs iterate hold-off remaining, but I think we can live with the reduction now. If it proves to be a noticable problem then we can look towards RCU based lookups, I think. Otherwise it looks OK to me.
We only walk the list during:
- mount time for quotacheck
- umount time
- full quotaoff
in the first two cases lookups can't happen at all, and in the latter they at least shoudn't get this far. So I really don't think it's a problem. And the full quotaoff even for quota accounting is something I'd like to remove sooner or later, it just causes a lot of corner cases for very little gain.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
PATCH v2 7/8 xfs: remove the per-filesystem list of dquots
In reply to Christoph HellwigInstead of keeping a separate per-filesystem list of dquots we can walk the radix tree for the two places where we need to iterate all quota structures.
--- fs/xfs/xfs_dquot.c | 37 ++---- fs/xfs/xfs_dquot.h | 3 fs/xfs/xfs_qm.c | 283 +++++++++++++++++++++++------------------------------ fs/xfs/xfs_qm.h | 4 4 files changed, 142 insertions(+), 185 deletions(-)
V2: remove the useless flags/type argument to the iterator callbacks
fs/xfs/xfs_dquot.c +3 -91
@@ -44,10 +44,9 @@* * ip->i_lock * qi->qi_tree_lock -* qi->qi_dqlist_lock -* dquot->q_qlock (xfs_dqlock() and friends) -* dquot->q_flush (xfs_dqflock() and friends) -* qi->qi_lru_lock +* dquot->q_qlock (xfs_dqlock() and friends) +* dquot->q_flush (xfs_dqflock() and friends) +* qi->qi_lru_lock * * If two dquots need to be locked the order is user before group/project, * otherwise by the lowest id first, see xfs_dqlock2.
@@ -729,20 +728,12 @@ restart: }/* -* Attach this dquot to this filesystem's list of all dquots, -* kept inside the mount structure in m_quotainfo field -*/ -mutex_lock (&qi->qi_dqlist_lock); - -/* * We return a locked dquot to the caller, with a reference taken */ xfs_dqlock (dqp); dqp->q_nrefs =1 ; -list_add (&dqp->q_mplist, &qi->qi_dqlist); qi->qi_dquots++; -mutex_unlock (&qi->qi_dqlist_lock);mutex_unlock (&qi->qi_tree_lock); dqret:
@@ -1018,85 +1009,6 @@ xfs_dqlock2( }/* -* Take a dquot out of the mount's dqlist as well as the hashlist. This is -* called via unmount as well as quotaoff, and the purge will always succeed. -*/ -void -xfs_qm_dqpurge ( -struct xfs_dquot *dqp) -{ -struct xfs_mount *mp = dqp->q_mount; -struct xfs_quotainfo *qi = mp->m_quotainfo; - -xfs_dqlock (dqp); - -/* -* If we're turning off quotas, we have to make sure that, for -* example, we don't delete quota disk blocks while dquots are -* in the process of getting written to those disk blocks. -* This dquot might well be on AIL, and we can't leave it there -* if we're turning off quotas. Basically, we need this flush -* lock, and are willing to block on it. -*/ -if (!xfs_dqflock_nowait (dqp)) { -/* -* Block on the flush lock after nudging dquot buffer, -* if it is incore. -*/ -xfs_dqflock_pushbuf_wait (dqp); - } - -/* -* If we are turning this type of quotas off, we don't care -* about the dirty metadata sitting in this dquot. OTOH, if -* we're unmounting, we do care, so we flush it and wait. -*/ -if (XFS_DQ_IS_DIRTY (dqp)) { -int error; - -/* -* We don't care about getting disk errors here. We need -* to purge this dquot anyway, so we go ahead regardless. -*/ - error =xfs_qm_dqflush (dqp,SYNC_WAIT ); -if (error) -xfs_warn (mp,"%s: dquot %p flush failed" , - __func__, dqp); -xfs_dqflock (dqp); - } - -ASSERT (atomic_read (&dqp->q_pincount) ==0 ); -ASSERT (XFS_FORCED_SHUTDOWN (mp) || - !(dqp->q_logitem.qli_item.li_flags &XFS_LI_IN_AIL )); - -xfs_dqfunlock (dqp); -xfs_dqunlock (dqp); - -mutex_lock (&qi->qi_tree_lock); -radix_tree_delete (XFS_DQUOT_TREE (qi, dqp->q_core.d_flags), -be32_to_cpu (dqp->q_core.d_id)); -mutex_unlock (&qi->qi_tree_lock); - -mutex_lock (&qi->qi_dqlist_lock); -list_del_init (&dqp->q_mplist); - qi->qi_dqreclaims++; - qi->qi_dquots--; -mutex_unlock (&qi->qi_dqlist_lock); - -/* -* We move dquots to the freelist as soon as their reference count -* hits zero, so it really should be on the freelist here. -*/ -mutex_lock (&qi->qi_lru_lock); -ASSERT (!list_empty (&dqp->q_lru)); -list_del_init (&dqp->q_lru); - qi->qi_lru_count--; -mutex_unlock (&qi->qi_lru_lock); - -xfs_qm_dqdestroy (dqp); -} - -/* * Give the buffer a little push if it is incore and * wait on the flush lock. */
fs/xfs/xfs_qm.c +227 -196
490 lines not on this page · raw message
fs/xfs/xfs_qm.h +0 -4
@@ -63,11 +63,7 @@ typedef struct xfs_quotainfo {struct list_head qi_lru_list;struct mutex qi_lru_lock;int qi_lru_count; -struct list_head qi_dqlist;/* all dquots in filesys */ -struct mutex qi_dqlist_lock;int qi_dquots; -int qi_dqreclaims;/* a change here indicates -a removal in the dqlist */ time_t qi_btimelimit;/* limit for blks timer */ time_t qi_itimelimit;/* limit for inodes timer */ time_t qi_rtbtimelimit;/* limit for rt blks timer */
fs/xfs/xfs_dquot.h +0 -2
@@ -38,7 +38,6 @@ struct xfs_trans; typedef struct xfs_dquot { uint dq_flags; /* various flags (XFS_DQ_*) */ struct list_head q_lru; /* global free list of dquots */ - struct list_head q_mplist; /* mount's list of dquots */ struct xfs_mount*q_mount; /* filesystem this relates to */ struct xfs_trans*q_transp; /* trans this belongs to currently */ uint q_nrefs; /* # active refs from inodes */
@@ -143,7 +142,6 @@ extern int xfs_qm_dqread(struct xfs_mou uint, struct xfs_dquot **);extern void xfs_qm_dqdestroy (xfs_dquot_t *);extern int xfs_qm_dqflush (xfs_dquot_t *,uint ); -extern void xfs_qm_dqpurge (xfs_dquot_t *);extern void xfs_qm_dqunpin_wait (xfs_dquot_t *);extern void xfs_qm_adjust_dqtimers (xfs_mount_t *,xfs_disk_dquot_t *);
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
PATCH 8/8 xfs: remove the global xfs_Gqm structure
In reply to Christoph HellwigIf we initialize the slab caches for the quote code when XFS is loaded there is no need for a global and reference counted quota manager structure. Drop all this overhead and also fix the error handling during quota initialization.
--- fs/xfs/xfs_dquot.c | 35 +++++++++++- fs/xfs/xfs_qm.c | 132 ----------------------------------------------- fs/xfs/xfs_qm.h | 15 ----- fs/xfs/xfs_qm_bhv.c | 16 ----- fs/xfs/xfs_super.c | 10 ++- fs/xfs/xfs_super.h | 8 +- fs/xfs/xfs_trans_dquot.c | 4 - 7 files changed, 46 insertions(+), 174 deletions(-)
fs/xfs/xfs_dquot.c +33 -2
@@ -59,6 +59,9 @@ int xfs_dqreq_num;int xfs_dqerror_mod =33 ;#endif +struct kmem_zone *xfs_qm_dqtrxzone; +static struct kmem_zone *xfs_qm_dqzone; +static struct lock_class_key xfs_dquot_other_class;/*
@@ -71,7 +74,7 @@ xfs_qm_dqdestroy(ASSERT (list_empty (&dqp->q_lru));mutex_destroy (&dqp->q_qlock); -kmem_zone_free (xfs_Gqm->qm_dqzone, dqp); +kmem_zone_free (xfs_qm_dqzone, dqp);XFS_STATS_DEC (xs_qm_dquot); }
@@ -491,7 +494,7 @@ xfs_qm_dqread(int cancelflags =0 ; - dqp =kmem_zone_zalloc (xfs_Gqm->qm_dqzone,KM_SLEEP ); + dqp =kmem_zone_zalloc (xfs_qm_dqzone,KM_SLEEP ); dqp->dq_flags = type; dqp->q_core.d_id =cpu_to_be32 (id);
@@ -1051,3 +1054,31 @@ xfs_dqflock_pushbuf_wait( out_lock:xfs_dqflock (dqp); } + +int __init +xfs_qm_init (void ) +{ + xfs_qm_dqzone = +kmem_zone_init (sizeof (struct xfs_dquot ),"xfs_dquot" ); +if (!xfs_qm_dqzone) + goto out; + + xfs_qm_dqtrxzone = +kmem_zone_init (sizeof (struct xfs_dquot_acct ),"xfs_dqtrx" ); +if (!xfs_qm_dqtrxzone) + goto out_free_dqzone; + +return 0 ; + +out_free_dqzone: +kmem_zone_destroy (xfs_qm_dqzone); +out: +return -ENOMEM ; +} + +void __exit +xfs_qm_exit (void ) +{ +kmem_zone_destroy (xfs_qm_dqtrxzone); +kmem_zone_destroy (xfs_qm_dqzone); +}
fs/xfs/xfs_qm.c +0 -132
164 lines not on this page · raw message
fs/xfs/xfs_qm.h +1 -14
@@ -22,13 +22,9 @@#include "xfs_dquot.h" #include "xfs_quota_priv.h" -struct xfs_qm ;struct xfs_inode ; -extern struct mutex xfs_Gqm_lock; -extern struct xfs_qm *xfs_Gqm; -extern kmem_zone_t *qm_dqzone; -extern kmem_zone_t *qm_dqtrxzone; +extern struct kmem_zone *xfs_qm_dqtrxzone;/* * This defines the unit of allocation of dquots.
@@ -42,15 +38,6 @@ extern kmem_zone_t *qm_dqtrxzone;#define XFS_DQUOT_CLUSTER_SIZE_FSB (xfs_filblks_t)1/* -* Quota Manager (global) structure. Lives only in core. -*/ -typedef struct xfs_qm { -uint qm_nrefs;/* file systems with quota on */ -kmem_zone_t *qm_dqzone;/* dquot mem-alloc zone */ -kmem_zone_t *qm_dqtrxzone;/* t_dqinfo of transactions */ -}xfs_qm_t ; - -/* * Various quota information for individual filesystems. * The mount structure keeps a pointer to this. */
fs/xfs/xfs_qm_bhv.c +0 -16
@@ -86,19 +86,3 @@ xfs_qm_statvfs(xfs_qm_dqput (dqp); } } - -void __init -xfs_qm_init (void ) -{ -printk (KERN_INFO "SGI XFS Quota Management subsystem\n" ); -mutex_init (&xfs_Gqm_lock); -} - -void __exit -xfs_qm_exit (void ) -{ -if (qm_dqzone) -kmem_zone_destroy (qm_dqzone); -if (qm_dqtrxzone) -kmem_zone_destroy (qm_dqtrxzone); -}
fs/xfs/xfs_trans_dquot.c +2 -2
@@ -876,7 +876,7 @@ STATIC voidxfs_trans_alloc_dqinfo ( xfs_trans_t *tp) { - tp->t_dqinfo =kmem_zone_zalloc (xfs_Gqm->qm_dqtrxzone,KM_SLEEP ); + tp->t_dqinfo =kmem_zone_zalloc (xfs_qm_dqtrxzone,KM_SLEEP ); }void
@@ -885,6 +885,6 @@ xfs_trans_free_dqinfo( {if (!tp->t_dqinfo)return ; -kmem_zone_free (xfs_Gqm->qm_dqtrxzone, tp->t_dqinfo); +kmem_zone_free (xfs_qm_dqtrxzone, tp->t_dqinfo); tp->t_dqinfo =NULL ; }
fs/xfs/xfs_super.c +7 -3
@@ -1651,13 +1651,17 @@ init_xfs_fs(void)if (error) goto out_cleanup_procfs; -vfs_initquota (); + error =xfs_qm_init (); +if (error) + goto out_sysctl_unregister; error =register_filesystem (&xfs_fs_type);if (error) - goto out_sysctl_unregister; + goto out_qm_exit;return 0 ; + out_qm_exit: +xfs_qm_exit (); out_sysctl_unregister:xfs_sysctl_unregister (); out_cleanup_procfs:
@@ -1679,7 +1683,7 @@ init_xfs_fs(void) STATIC void __exitexit_xfs_fs (void ) { -vfs_exitquota (); +xfs_qm_exit ();unregister_filesystem (&xfs_fs_type);xfs_sysctl_unregister ();xfs_cleanup_procfs ();
fs/xfs/xfs_super.h +3 -5
@@ -21,13 +21,11 @@#include <linux/exportfs.h> #ifdef CONFIG_XFS_QUOTA -extern void xfs_qm_init (void ); +extern int xfs_qm_init (void );extern void xfs_qm_exit (void ); -# define vfs_initquota () xfs_qm_init() -# define vfs_exitquota () xfs_qm_exit()#else -# define vfs_initquota () do { } while (0) -# define vfs_exitquota () do { } while (0) +# define xfs_qm_init () (0) +# define xfs_qm_exit () do { } while (0)#endif #ifdef CONFIG_XFS_POSIX_ACL
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs