xfs: remove the global xfs_Gqm structure
If we initialize the slab caches for the quota 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. Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Ben Myers <bpm@sgi.com>
This commit is contained in:
parent
b84a3a9675
commit
a05931ceb0
@ -59,6 +59,9 @@ int xfs_dqreq_num;
|
|||||||
int xfs_dqerror_mod = 33;
|
int xfs_dqerror_mod = 33;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct kmem_zone *xfs_qm_dqtrxzone;
|
||||||
|
static struct kmem_zone *xfs_qm_dqzone;
|
||||||
|
|
||||||
static struct lock_class_key xfs_dquot_other_class;
|
static struct lock_class_key xfs_dquot_other_class;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -71,7 +74,7 @@ xfs_qm_dqdestroy(
|
|||||||
ASSERT(list_empty(&dqp->q_lru));
|
ASSERT(list_empty(&dqp->q_lru));
|
||||||
|
|
||||||
mutex_destroy(&dqp->q_qlock);
|
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);
|
XFS_STATS_DEC(xs_qm_dquot);
|
||||||
}
|
}
|
||||||
@ -491,7 +494,7 @@ xfs_qm_dqread(
|
|||||||
int cancelflags = 0;
|
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->dq_flags = type;
|
||||||
dqp->q_core.d_id = cpu_to_be32(id);
|
dqp->q_core.d_id = cpu_to_be32(id);
|
||||||
@ -1040,3 +1043,31 @@ xfs_dqflock_pushbuf_wait(
|
|||||||
out_lock:
|
out_lock:
|
||||||
xfs_dqflock(dqp);
|
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);
|
||||||
|
}
|
||||||
|
132
fs/xfs/xfs_qm.c
132
fs/xfs/xfs_qm.c
@ -48,126 +48,10 @@
|
|||||||
* quota functionality, including maintaining the freelist and hash
|
* quota functionality, including maintaining the freelist and hash
|
||||||
* tables of dquots.
|
* tables of dquots.
|
||||||
*/
|
*/
|
||||||
struct mutex xfs_Gqm_lock;
|
|
||||||
struct xfs_qm *xfs_Gqm;
|
|
||||||
|
|
||||||
kmem_zone_t *qm_dqzone;
|
|
||||||
kmem_zone_t *qm_dqtrxzone;
|
|
||||||
|
|
||||||
STATIC int xfs_qm_init_quotainos(xfs_mount_t *);
|
STATIC int xfs_qm_init_quotainos(xfs_mount_t *);
|
||||||
STATIC int xfs_qm_init_quotainfo(xfs_mount_t *);
|
STATIC int xfs_qm_init_quotainfo(xfs_mount_t *);
|
||||||
STATIC int xfs_qm_shake(struct shrinker *, struct shrink_control *);
|
STATIC int xfs_qm_shake(struct shrinker *, struct shrink_control *);
|
||||||
|
|
||||||
/*
|
|
||||||
* Initialize the XQM structure.
|
|
||||||
* Note that there is not one quota manager per file system.
|
|
||||||
*/
|
|
||||||
STATIC struct xfs_qm *
|
|
||||||
xfs_Gqm_init(void)
|
|
||||||
{
|
|
||||||
xfs_qm_t *xqm;
|
|
||||||
|
|
||||||
xqm = kmem_zalloc(sizeof(xfs_qm_t), KM_SLEEP);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* dquot zone. we register our own low-memory callback.
|
|
||||||
*/
|
|
||||||
if (!qm_dqzone) {
|
|
||||||
xqm->qm_dqzone = kmem_zone_init(sizeof(xfs_dquot_t),
|
|
||||||
"xfs_dquots");
|
|
||||||
qm_dqzone = xqm->qm_dqzone;
|
|
||||||
} else
|
|
||||||
xqm->qm_dqzone = qm_dqzone;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The t_dqinfo portion of transactions.
|
|
||||||
*/
|
|
||||||
if (!qm_dqtrxzone) {
|
|
||||||
xqm->qm_dqtrxzone = kmem_zone_init(sizeof(xfs_dquot_acct_t),
|
|
||||||
"xfs_dqtrx");
|
|
||||||
qm_dqtrxzone = xqm->qm_dqtrxzone;
|
|
||||||
} else
|
|
||||||
xqm->qm_dqtrxzone = qm_dqtrxzone;
|
|
||||||
|
|
||||||
xqm->qm_nrefs = 0;
|
|
||||||
return xqm;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Destroy the global quota manager when its reference count goes to zero.
|
|
||||||
*/
|
|
||||||
STATIC void
|
|
||||||
xfs_qm_destroy(
|
|
||||||
struct xfs_qm *xqm)
|
|
||||||
{
|
|
||||||
ASSERT(xqm != NULL);
|
|
||||||
ASSERT(xqm->qm_nrefs == 0);
|
|
||||||
|
|
||||||
kmem_free(xqm);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Called at mount time to let XQM know that another file system is
|
|
||||||
* starting quotas. This isn't crucial information as the individual mount
|
|
||||||
* structures are pretty independent, but it helps the XQM keep a
|
|
||||||
* global view of what's going on.
|
|
||||||
*/
|
|
||||||
/* ARGSUSED */
|
|
||||||
STATIC int
|
|
||||||
xfs_qm_hold_quotafs_ref(
|
|
||||||
struct xfs_mount *mp)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Need to lock the xfs_Gqm structure for things like this. For example,
|
|
||||||
* the structure could disappear between the entry to this routine and
|
|
||||||
* a HOLD operation if not locked.
|
|
||||||
*/
|
|
||||||
mutex_lock(&xfs_Gqm_lock);
|
|
||||||
|
|
||||||
if (!xfs_Gqm) {
|
|
||||||
xfs_Gqm = xfs_Gqm_init();
|
|
||||||
if (!xfs_Gqm) {
|
|
||||||
mutex_unlock(&xfs_Gqm_lock);
|
|
||||||
return ENOMEM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We can keep a list of all filesystems with quotas mounted for
|
|
||||||
* debugging and statistical purposes, but ...
|
|
||||||
* Just take a reference and get out.
|
|
||||||
*/
|
|
||||||
xfs_Gqm->qm_nrefs++;
|
|
||||||
mutex_unlock(&xfs_Gqm_lock);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Release the reference that a filesystem took at mount time,
|
|
||||||
* so that we know when we need to destroy the entire quota manager.
|
|
||||||
*/
|
|
||||||
/* ARGSUSED */
|
|
||||||
STATIC void
|
|
||||||
xfs_qm_rele_quotafs_ref(
|
|
||||||
struct xfs_mount *mp)
|
|
||||||
{
|
|
||||||
ASSERT(xfs_Gqm);
|
|
||||||
ASSERT(xfs_Gqm->qm_nrefs > 0);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Destroy the entire XQM. If somebody mounts with quotaon, this'll
|
|
||||||
* be restarted.
|
|
||||||
*/
|
|
||||||
mutex_lock(&xfs_Gqm_lock);
|
|
||||||
if (--xfs_Gqm->qm_nrefs == 0) {
|
|
||||||
xfs_qm_destroy(xfs_Gqm);
|
|
||||||
xfs_Gqm = NULL;
|
|
||||||
}
|
|
||||||
mutex_unlock(&xfs_Gqm_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We use the batch lookup interface to iterate over the dquots as it
|
* We use the batch lookup interface to iterate over the dquots as it
|
||||||
* currently is the only interface into the radix tree code that allows
|
* currently is the only interface into the radix tree code that allows
|
||||||
@ -738,13 +622,6 @@ xfs_qm_init_quotainfo(
|
|||||||
|
|
||||||
ASSERT(XFS_IS_QUOTA_RUNNING(mp));
|
ASSERT(XFS_IS_QUOTA_RUNNING(mp));
|
||||||
|
|
||||||
/*
|
|
||||||
* Tell XQM that we exist as soon as possible.
|
|
||||||
*/
|
|
||||||
if ((error = xfs_qm_hold_quotafs_ref(mp))) {
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
qinf = mp->m_quotainfo = kmem_zalloc(sizeof(xfs_quotainfo_t), KM_SLEEP);
|
qinf = mp->m_quotainfo = kmem_zalloc(sizeof(xfs_quotainfo_t), KM_SLEEP);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -850,17 +727,9 @@ xfs_qm_destroy_quotainfo(
|
|||||||
|
|
||||||
qi = mp->m_quotainfo;
|
qi = mp->m_quotainfo;
|
||||||
ASSERT(qi != NULL);
|
ASSERT(qi != NULL);
|
||||||
ASSERT(xfs_Gqm != NULL);
|
|
||||||
|
|
||||||
unregister_shrinker(&qi->qi_shrinker);
|
unregister_shrinker(&qi->qi_shrinker);
|
||||||
|
|
||||||
/*
|
|
||||||
* Release the reference that XQM kept, so that we know
|
|
||||||
* when the XQM structure should be freed. We cannot assume
|
|
||||||
* that xfs_Gqm is non-null after this point.
|
|
||||||
*/
|
|
||||||
xfs_qm_rele_quotafs_ref(mp);
|
|
||||||
|
|
||||||
if (qi->qi_uquotaip) {
|
if (qi->qi_uquotaip) {
|
||||||
IRELE(qi->qi_uquotaip);
|
IRELE(qi->qi_uquotaip);
|
||||||
qi->qi_uquotaip = NULL; /* paranoia */
|
qi->qi_uquotaip = NULL; /* paranoia */
|
||||||
@ -1447,7 +1316,6 @@ xfs_qm_quotacheck(
|
|||||||
* We must turn off quotas.
|
* We must turn off quotas.
|
||||||
*/
|
*/
|
||||||
ASSERT(mp->m_quotainfo != NULL);
|
ASSERT(mp->m_quotainfo != NULL);
|
||||||
ASSERT(xfs_Gqm != NULL);
|
|
||||||
xfs_qm_destroy_quotainfo(mp);
|
xfs_qm_destroy_quotainfo(mp);
|
||||||
if (xfs_mount_reset_sbqflags(mp)) {
|
if (xfs_mount_reset_sbqflags(mp)) {
|
||||||
xfs_warn(mp,
|
xfs_warn(mp,
|
||||||
|
@ -22,13 +22,9 @@
|
|||||||
#include "xfs_dquot.h"
|
#include "xfs_dquot.h"
|
||||||
#include "xfs_quota_priv.h"
|
#include "xfs_quota_priv.h"
|
||||||
|
|
||||||
struct xfs_qm;
|
|
||||||
struct xfs_inode;
|
struct xfs_inode;
|
||||||
|
|
||||||
extern struct mutex xfs_Gqm_lock;
|
extern struct kmem_zone *xfs_qm_dqtrxzone;
|
||||||
extern struct xfs_qm *xfs_Gqm;
|
|
||||||
extern kmem_zone_t *qm_dqzone;
|
|
||||||
extern kmem_zone_t *qm_dqtrxzone;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This defines the unit of allocation of dquots.
|
* This defines the unit of allocation of dquots.
|
||||||
@ -41,15 +37,6 @@ extern kmem_zone_t *qm_dqtrxzone;
|
|||||||
*/
|
*/
|
||||||
#define XFS_DQUOT_CLUSTER_SIZE_FSB (xfs_filblks_t)1
|
#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.
|
* Various quota information for individual filesystems.
|
||||||
* The mount structure keeps a pointer to this.
|
* The mount structure keeps a pointer to this.
|
||||||
|
@ -156,19 +156,3 @@ xfs_qm_newmount(
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
@ -1654,13 +1654,17 @@ init_xfs_fs(void)
|
|||||||
if (error)
|
if (error)
|
||||||
goto out_cleanup_procfs;
|
goto out_cleanup_procfs;
|
||||||
|
|
||||||
vfs_initquota();
|
error = xfs_qm_init();
|
||||||
|
if (error)
|
||||||
|
goto out_sysctl_unregister;
|
||||||
|
|
||||||
error = register_filesystem(&xfs_fs_type);
|
error = register_filesystem(&xfs_fs_type);
|
||||||
if (error)
|
if (error)
|
||||||
goto out_sysctl_unregister;
|
goto out_qm_exit;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
out_qm_exit:
|
||||||
|
xfs_qm_exit();
|
||||||
out_sysctl_unregister:
|
out_sysctl_unregister:
|
||||||
xfs_sysctl_unregister();
|
xfs_sysctl_unregister();
|
||||||
out_cleanup_procfs:
|
out_cleanup_procfs:
|
||||||
@ -1682,7 +1686,7 @@ init_xfs_fs(void)
|
|||||||
STATIC void __exit
|
STATIC void __exit
|
||||||
exit_xfs_fs(void)
|
exit_xfs_fs(void)
|
||||||
{
|
{
|
||||||
vfs_exitquota();
|
xfs_qm_exit();
|
||||||
unregister_filesystem(&xfs_fs_type);
|
unregister_filesystem(&xfs_fs_type);
|
||||||
xfs_sysctl_unregister();
|
xfs_sysctl_unregister();
|
||||||
xfs_cleanup_procfs();
|
xfs_cleanup_procfs();
|
||||||
|
@ -21,13 +21,11 @@
|
|||||||
#include <linux/exportfs.h>
|
#include <linux/exportfs.h>
|
||||||
|
|
||||||
#ifdef CONFIG_XFS_QUOTA
|
#ifdef CONFIG_XFS_QUOTA
|
||||||
extern void xfs_qm_init(void);
|
extern int xfs_qm_init(void);
|
||||||
extern void xfs_qm_exit(void);
|
extern void xfs_qm_exit(void);
|
||||||
# define vfs_initquota() xfs_qm_init()
|
|
||||||
# define vfs_exitquota() xfs_qm_exit()
|
|
||||||
#else
|
#else
|
||||||
# define vfs_initquota() do { } while (0)
|
# define xfs_qm_init() (0)
|
||||||
# define vfs_exitquota() do { } while (0)
|
# define xfs_qm_exit() do { } while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_XFS_POSIX_ACL
|
#ifdef CONFIG_XFS_POSIX_ACL
|
||||||
|
@ -875,7 +875,7 @@ STATIC void
|
|||||||
xfs_trans_alloc_dqinfo(
|
xfs_trans_alloc_dqinfo(
|
||||||
xfs_trans_t *tp)
|
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
|
void
|
||||||
@ -884,6 +884,6 @@ xfs_trans_free_dqinfo(
|
|||||||
{
|
{
|
||||||
if (!tp->t_dqinfo)
|
if (!tp->t_dqinfo)
|
||||||
return;
|
return;
|
||||||
kmem_zone_free(xfs_Gqm->qm_dqtrxzone, tp->t_dqinfo);
|
kmem_zone_free(xfs_qm_dqtrxzone, tp->t_dqinfo);
|
||||||
tp->t_dqinfo = NULL;
|
tp->t_dqinfo = NULL;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user