From: Johann Lombardi Date: Thu, 6 Sep 2012 10:54:13 +0000 (+0200) Subject: LU-1842 quota: define quota records for glb/slv indexes X-Git-Tag: 2.3.51~124 X-Git-Url: https://git.whamcloud.com/gitweb?a=commitdiff_plain;h=bd12686ac514c0379eaf2834544b7562739f11f2;p=fs%2Flustre-release.git LU-1842 quota: define quota records for glb/slv indexes This patch defines lquota_glb_rec & lquota_slv_rec which are the record which will be used with the global & slave index files. It also introduces the global quota lu_context_key which will be used by all quota-level handlers. The lquota module init/exit function are now defined in lquota_lib.c which calls the old quota init/exit function for the time being. Finally, this patch also modifies lquotactl_slv() to collect enforcement information. Signed-off-by: Johann Lombardi Change-Id: I2b261bd8433a5e6bd64c2de2710bca32bf606122 Reviewed-on: http://review.whamcloud.com/3886 Reviewed-by: Andreas Dilger Tested-by: Hudson Tested-by: Maloo Reviewed-by: Fan Yong Reviewed-by: Niu Yawei --- diff --git a/lustre/include/dt_object.h b/lustre/include/dt_object.h index c57fc00..5455194 100644 --- a/lustre/include/dt_object.h +++ b/lustre/include/dt_object.h @@ -223,6 +223,12 @@ extern const struct dt_index_features dt_otable_features; /* index features supported by the accounting objects */ extern const struct dt_index_features dt_acct_features; +/* index features supported by the quota global indexes */ +extern const struct dt_index_features dt_quota_glb_features; + +/* index features supported by the quota slave indexes */ +extern const struct dt_index_features dt_quota_slv_features; + /** * This is a general purpose dt allocation hint. * It now contains the parent object. diff --git a/lustre/include/lquota.h b/lustre/include/lquota.h index 13d1021..9f2e3e5 100644 --- a/lustre/include/lquota.h +++ b/lustre/include/lquota.h @@ -32,14 +32,13 @@ #ifndef _LUSTRE_LQUOTA_H #define _LUSTRE_LQUOTA_H -/* - * Space accounting support - * Format of an accounting record, providing disk usage information for a given - * user or group - */ -struct acct_rec { /* 16 bytes */ - __u64 bspace; /* current space in use */ - __u64 ispace; /* current # inodes in use */ +/* Gather all quota record type in an union that can be used to read any records + * from disk. All fields of these records must be 64-bit aligned, otherwise the + * OSD layer may swab them incorrectly. */ +union lquota_rec { + struct lquota_glb_rec lqr_glb_rec; + struct lquota_slv_rec lqr_slv_rec; + struct lquota_acct_rec lqr_acct_rec; }; /* Name used in the configuration logs to identify the default metadata pool diff --git a/lustre/include/lustre/lustre_idl.h b/lustre/include/lustre/lustre_idl.h index 41b1af1..02a4e23 100644 --- a/lustre/include/lustre/lustre_idl.h +++ b/lustre/include/lustre/lustre_idl.h @@ -1820,6 +1820,39 @@ struct quota_adjust_qunit { }; extern void lustre_swab_quota_adjust_qunit(struct quota_adjust_qunit *q); +/* + * Space accounting support + * Format of an accounting record, providing disk usage information for a given + * user or group + */ +struct lquota_acct_rec { /* 16 bytes */ + __u64 bspace; /* current space in use */ + __u64 ispace; /* current # inodes in use */ +}; + +/* + * Global quota index support + * Format of a global record, providing global quota settings for a given quota + * identifier + */ +struct lquota_glb_rec { /* 32 bytes */ + __u64 qbr_hardlimit; /* quota hard limit, in #inodes or kbytes */ + __u64 qbr_softlimit; /* quota soft limit, in #inodes or kbytes */ + __u64 qbr_time; /* grace time, in seconds */ + __u64 qbr_granted; /* how much is granted to slaves, in #inodes or + * kbytes */ +}; + +/* + * Slave index support + * Format of a slave record, recording how much space is granted to a given + * slave + */ +struct lquota_slv_rec { /* 8 bytes */ + __u64 qsr_granted; /* space granted to the slave for the key=ID, + * in #inodes or kbytes */ +}; + /* flags is shared among quota structures */ #define LQUOTA_FLAGS_GRP 1UL /* 0 is user, 1 is group */ #define LQUOTA_FLAGS_BLK 2UL /* 0 is inode, 1 is block */ diff --git a/lustre/obdclass/dt_object.c b/lustre/obdclass/dt_object.c index 052cb4e..c231814 100644 --- a/lustre/obdclass/dt_object.c +++ b/lustre/obdclass/dt_object.c @@ -576,8 +576,32 @@ const struct dt_index_features dt_acct_features = { .dif_flags = DT_IND_UPDATE, .dif_keysize_min = sizeof(__u64), /* 64-bit uid/gid */ .dif_keysize_max = sizeof(__u64), /* 64-bit uid/gid */ - .dif_recsize_min = sizeof(struct acct_rec), /* 32 bytes */ - .dif_recsize_max = sizeof(struct acct_rec), /* 32 bytes */ + .dif_recsize_min = sizeof(struct lquota_acct_rec), /* 16 bytes */ + .dif_recsize_max = sizeof(struct lquota_acct_rec), /* 16 bytes */ .dif_ptrsize = 4 }; EXPORT_SYMBOL(dt_acct_features); + +/* global quota files */ +const struct dt_index_features dt_quota_glb_features = { + .dif_flags = DT_IND_UPDATE, + /* a different key would have to be used for per-directory quota */ + .dif_keysize_min = sizeof(__u64), /* 64-bit uid/gid */ + .dif_keysize_max = sizeof(__u64), /* 64-bit uid/gid */ + .dif_recsize_min = sizeof(struct lquota_glb_rec), /* 32 bytes */ + .dif_recsize_max = sizeof(struct lquota_glb_rec), /* 32 bytes */ + .dif_ptrsize = 4 +}; +EXPORT_SYMBOL(dt_quota_glb_features); + +/* slave quota files */ +const struct dt_index_features dt_quota_slv_features = { + .dif_flags = DT_IND_UPDATE, + /* a different key would have to be used for per-directory quota */ + .dif_keysize_min = sizeof(__u64), /* 64-bit uid/gid */ + .dif_keysize_max = sizeof(__u64), /* 64-bit uid/gid */ + .dif_recsize_min = sizeof(struct lquota_slv_rec), /* 8 bytes */ + .dif_recsize_max = sizeof(struct lquota_slv_rec), /* 8 bytes */ + .dif_ptrsize = 4 +}; +EXPORT_SYMBOL(dt_quota_slv_features); diff --git a/lustre/osd-ldiskfs/osd_quota.c b/lustre/osd-ldiskfs/osd_quota.c index c39f829..1d26b48 100644 --- a/lustre/osd-ldiskfs/osd_quota.c +++ b/lustre/osd-ldiskfs/osd_quota.c @@ -102,7 +102,7 @@ static int osd_acct_index_lookup(const struct lu_env *env, struct osd_thread_info *info = osd_oti_get(env); struct if_dqblk *dqblk = &info->oti_dqblk; struct super_block *sb = osd_sb(osd_obj2dev(osd_dt_obj(dtobj))); - struct acct_rec *rec = (struct acct_rec *)dtrec; + struct lquota_acct_rec *rec = (struct lquota_acct_rec *)dtrec; __u64 id = *((__u64 *)dtkey); int rc; diff --git a/lustre/osd-zfs/osd_quota.c b/lustre/osd-zfs/osd_quota.c index 68e8dd5..1f9e2d2 100644 --- a/lustre/osd-zfs/osd_quota.c +++ b/lustre/osd-zfs/osd_quota.c @@ -71,7 +71,7 @@ static int osd_acct_index_lookup(const struct lu_env *env, { struct osd_thread_info *info = osd_oti_get(env); char *buf = info->oti_buf; - struct acct_rec *rec = (struct acct_rec *)dtrec; + struct lquota_acct_rec *rec = (struct lquota_acct_rec *)dtrec; struct osd_object *obj = osd_dt_obj(dtobj); struct osd_device *osd = osd_obj2dev(obj); int rc; @@ -249,7 +249,7 @@ static int osd_it_acct_rec(const struct lu_env *env, struct osd_thread_info *info = osd_oti_get(env); char *buf = info->oti_buf; struct osd_it_quota *it = (struct osd_it_quota *)di; - struct acct_rec *rec = (struct acct_rec *)dtrec; + struct lquota_acct_rec *rec = (struct lquota_acct_rec *)dtrec; struct osd_object *obj = it->oiq_obj; struct osd_device *osd = osd_obj2dev(obj); int bytes_read; diff --git a/lustre/ptlrpc/wiretest.c b/lustre/ptlrpc/wiretest.c index 443c518..1501413 100644 --- a/lustre/ptlrpc/wiretest.c +++ b/lustre/ptlrpc/wiretest.c @@ -1630,6 +1630,46 @@ void lustre_assert_wire_constants(void) LASSERTF(Q_FINVALIDATE == 0x800104, "found 0x%.8x\n", Q_FINVALIDATE); + /* Checks for struct lquota_acct_rec */ + LASSERTF((int)sizeof(struct lquota_acct_rec) == 16, "found %lld\n", + (long long)(int)sizeof(struct lquota_acct_rec)); + LASSERTF((int)offsetof(struct lquota_acct_rec, bspace) == 0, "found %lld\n", + (long long)(int)offsetof(struct lquota_acct_rec, bspace)); + LASSERTF((int)sizeof(((struct lquota_acct_rec *)0)->bspace) == 8, "found %lld\n", + (long long)(int)sizeof(((struct lquota_acct_rec *)0)->bspace)); + LASSERTF((int)offsetof(struct lquota_acct_rec, ispace) == 8, "found %lld\n", + (long long)(int)offsetof(struct lquota_acct_rec, ispace)); + LASSERTF((int)sizeof(((struct lquota_acct_rec *)0)->ispace) == 8, "found %lld\n", + (long long)(int)sizeof(((struct lquota_acct_rec *)0)->ispace)); + + /* Checks for struct lquota_glb_rec */ + LASSERTF((int)sizeof(struct lquota_glb_rec) == 32, "found %lld\n", + (long long)(int)sizeof(struct lquota_glb_rec)); + LASSERTF((int)offsetof(struct lquota_glb_rec, qbr_hardlimit) == 0, "found %lld\n", + (long long)(int)offsetof(struct lquota_glb_rec, qbr_hardlimit)); + LASSERTF((int)sizeof(((struct lquota_glb_rec *)0)->qbr_hardlimit) == 8, "found %lld\n", + (long long)(int)sizeof(((struct lquota_glb_rec *)0)->qbr_hardlimit)); + LASSERTF((int)offsetof(struct lquota_glb_rec, qbr_softlimit) == 8, "found %lld\n", + (long long)(int)offsetof(struct lquota_glb_rec, qbr_softlimit)); + LASSERTF((int)sizeof(((struct lquota_glb_rec *)0)->qbr_softlimit) == 8, "found %lld\n", + (long long)(int)sizeof(((struct lquota_glb_rec *)0)->qbr_softlimit)); + LASSERTF((int)offsetof(struct lquota_glb_rec, qbr_time) == 16, "found %lld\n", + (long long)(int)offsetof(struct lquota_glb_rec, qbr_time)); + LASSERTF((int)sizeof(((struct lquota_glb_rec *)0)->qbr_time) == 8, "found %lld\n", + (long long)(int)sizeof(((struct lquota_glb_rec *)0)->qbr_time)); + LASSERTF((int)offsetof(struct lquota_glb_rec, qbr_granted) == 24, "found %lld\n", + (long long)(int)offsetof(struct lquota_glb_rec, qbr_granted)); + LASSERTF((int)sizeof(((struct lquota_glb_rec *)0)->qbr_granted) == 8, "found %lld\n", + (long long)(int)sizeof(((struct lquota_glb_rec *)0)->qbr_granted)); + + /* Checks for struct lquota_slv_rec */ + LASSERTF((int)sizeof(struct lquota_slv_rec) == 8, "found %lld\n", + (long long)(int)sizeof(struct lquota_slv_rec)); + LASSERTF((int)offsetof(struct lquota_slv_rec, qsr_granted) == 0, "found %lld\n", + (long long)(int)offsetof(struct lquota_slv_rec, qsr_granted)); + LASSERTF((int)sizeof(((struct lquota_slv_rec *)0)->qsr_granted) == 8, "found %lld\n", + (long long)(int)sizeof(((struct lquota_slv_rec *)0)->qsr_granted)); + /* Checks for struct niobuf_remote */ LASSERTF((int)sizeof(struct niobuf_remote) == 16, "found %lld\n", (long long)(int)sizeof(struct niobuf_remote)); diff --git a/lustre/quota/lproc_quota.c b/lustre/quota/lproc_quota.c index b385d07..6c8a5c8 100644 --- a/lustre/quota/lproc_quota.c +++ b/lustre/quota/lproc_quota.c @@ -176,12 +176,12 @@ static void *lprocfs_quota_seq_next(struct seq_file *p, void *v, loff_t *pos) */ static int lprocfs_quota_seq_show(struct seq_file *p, void *v) { - struct lquota_procfs *lqp = p->private; - const struct dt_it_ops *iops; - struct dt_it *it; - struct dt_key *key; - struct acct_rec rec; - int rc; + struct lquota_procfs *lqp = p->private; + const struct dt_it_ops *iops; + struct dt_it *it; + struct dt_key *key; + struct lquota_acct_rec rec; + int rc; LASSERT(lqp); if (lqp->lqp_obj == NULL) { diff --git a/lustre/quota/lquota_internal.h b/lustre/quota/lquota_internal.h index b39f633..22fc7a2 100644 --- a/lustre/quota/lquota_internal.h +++ b/lustre/quota/lquota_internal.h @@ -33,11 +33,61 @@ #define QTYPE_NAME(qtype) ((qtype) == USRQUOTA ? "usr" : "grp") +#define QIF_IFLAGS (QIF_INODES | QIF_ITIME | QIF_ILIMITS) +#define QIF_BFLAGS (QIF_SPACE | QIF_BTIME | QIF_BLIMITS) + +/* The biggest filename are the one used for slave index which are in the form + * of 0x%x-%s,glb_fid.f_oid,slv_uuid, that's to say: + * 2(0x) + 8(f_oid) + 1(-) + 40(UUID_MAX) which means 51 chars + '\0' */ +#define LQUOTA_NAME_MAX 52 + +/* reserved OID in FID_SEQ_QUOTA for local objects */ +enum lquota_local_oid { + LQUOTA_USR_OID = 1UL, /* slave index copy for user quota */ + LQUOTA_GRP_OID = 2UL, /* slave index copy for group quota */ + /* all OIDs after this are allocated dynamically by the QMT */ + LQUOTA_GENERATED_OID = 4096UL, +}; + +/* Common data shared by quota-level handlers. This is allocated per-thread to + * reduce stack consumption */ +struct lquota_thread_info { + union lquota_rec qti_rec; + struct lu_buf qti_lb; + struct lu_attr qti_attr; + struct dt_object_format qti_dof; + struct lustre_mdt_attrs qti_lma; + struct lu_fid qti_fid; + char qti_buf[LQUOTA_NAME_MAX]; +}; + +#define qti_glb_rec qti_rec.lqr_glb_rec +#define qti_acct_rec qti_rec.lqr_acct_rec +#define qti_slv_rec qti_rec.lqr_slv_rec + +extern struct lu_context_key lquota_thread_key; + +/* extract lquota_threa_info context from environment */ +static inline +struct lquota_thread_info *lquota_info(const struct lu_env *env) +{ + struct lquota_thread_info *info; + + info = lu_context_key_get(&env->le_ctx, &lquota_thread_key); + LASSERT(info); + return info; +} + /* lquota_lib.c */ struct dt_object *acct_obj_lookup(const struct lu_env *, struct dt_device *, - __u32); + int); /* lproc_quota.c */ extern struct file_operations lprocfs_quota_seq_fops; +/* quota_interface.c + * old quota module initialization routines, to be removed */ +int init_lustre_quota(void); +void exit_lustre_quota(void); + #endif /* _LQUOTA_INTERNAL_H */ diff --git a/lustre/quota/lquota_lib.c b/lustre/quota/lquota_lib.c index 0f5d984..51a0c49 100644 --- a/lustre/quota/lquota_lib.c +++ b/lustre/quota/lquota_lib.c @@ -21,11 +21,11 @@ * GPL HEADER END */ /* - * Copyright (c) 2011, 2012, Whamcloud, Inc. + * Copyright (c) 2011, 2012, Intel, Inc. * Use is subject to license terms. * - * Author: Johann Lombardi - * Author: Niu Yawei + * Author: Johann Lombardi + * Author: Niu Yawei */ #ifndef EXPORT_SYMTAB @@ -34,45 +34,101 @@ #define DEBUG_SUBSYSTEM S_LQUOTA +#include +#include +#include + #include "lquota_internal.h" -static struct dt_object_format dt_acct_format = { - .dof_type = DFT_INDEX, - .u.dof_idx.di_feat = &dt_acct_features -}; +/* register lquota key */ +LU_KEY_INIT_FINI(lquota, struct lquota_thread_info); +LU_CONTEXT_KEY_DEFINE(lquota, LCT_MD_THREAD | LCT_DT_THREAD | LCT_LOCAL); +LU_KEY_INIT_GENERIC(lquota); /** * Look-up accounting object to collect space usage information for user * or group. * - * \param env - is the environment passed by the caller - * \param dev - is the dt_device storing the accounting object - * \param oid - is the object id of the accounting object to initialize, must be - * either ACCT_USER_OID or ACCT_GROUP_OID. + * \param env - is the environment passed by the caller + * \param dev - is the dt_device storing the accounting object + * \param type - is the quota type, either USRQUOTA or GRPQUOTA */ struct dt_object *acct_obj_lookup(const struct lu_env *env, - struct dt_device *dev, __u32 oid) + struct dt_device *dev, int type) { - struct dt_object *obj = NULL; - struct lu_fid fid; - struct lu_attr attr; - int rc; + struct lquota_thread_info *qti = lquota_info(env); + struct dt_object *obj = NULL; ENTRY; - memset(&attr, 0, sizeof(attr)); - attr.la_valid = LA_MODE; - attr.la_mode = S_IFREG | S_IRUGO | S_IWUSR; - lu_local_obj_fid(&fid, oid); + lu_local_obj_fid(&qti->qti_fid, + type == USRQUOTA ? ACCT_USER_OID : ACCT_GROUP_OID); - /* lookup/create the accounting object */ - obj = dt_find_or_create(env, dev, &fid, &dt_acct_format, &attr); + /* lookup the accounting object */ + obj = dt_locate(env, dev, &qti->qti_fid); if (IS_ERR(obj)) RETURN(obj); + if (!dt_object_exists(obj)) { + lu_object_put(env, &obj->do_lu); + RETURN(ERR_PTR(-ENOENT)); + } + if (obj->do_index_ops == NULL) { + int rc; + /* set up indexing operations */ rc = obj->do_ops->do_index_try(env, obj, &dt_acct_features); if (rc) { + CERROR("%s: failed to set up indexing operations for %s" + " acct object rc:%d\n", + dev->dd_lu_dev.ld_obd->obd_name, + QTYPE_NAME(type), rc); + lu_object_put(env, &obj->do_lu); + RETURN(ERR_PTR(rc)); + } + } + RETURN(obj); +} + +/** + * Initialize slave index object to collect local quota limit for user or group. + * + * \param env - is the environment passed by the caller + * \param dev - is the dt_device storing the slave index object + * \param type - is the quota type, either USRQUOTA or GRPQUOTA + */ +static struct dt_object *quota_obj_lookup(const struct lu_env *env, + struct dt_device *dev, int type) +{ + struct lquota_thread_info *qti = lquota_info(env); + struct dt_object *obj = NULL; + ENTRY; + + qti->qti_fid.f_seq = FID_SEQ_QUOTA; + qti->qti_fid.f_oid = type == USRQUOTA ? LQUOTA_USR_OID : LQUOTA_GRP_OID; + qti->qti_fid.f_ver = 0; + + /* lookup the quota object */ + obj = dt_locate(env, dev, &qti->qti_fid); + if (IS_ERR(obj)) + RETURN(obj); + + if (!dt_object_exists(obj)) { + lu_object_put(env, &obj->do_lu); + RETURN(ERR_PTR(-ENOENT)); + } + + if (obj->do_index_ops == NULL) { + int rc; + + /* set up indexing operations */ + rc = obj->do_ops->do_index_try(env, obj, + &dt_quota_slv_features); + if (rc) { + CERROR("%s: failed to set up indexing operations for %s" + " slave index object rc:%d\n", + dev->dd_lu_dev.ld_obd->obd_name, + QTYPE_NAME(type), rc); lu_object_put(env, &obj->do_lu); RETURN(ERR_PTR(rc)); } @@ -93,51 +149,106 @@ struct dt_object *acct_obj_lookup(const struct lu_env *env, int lquotactl_slv(const struct lu_env *env, struct dt_device *dev, struct obd_quotactl *oqctl) { - struct acct_rec rec; - __u64 key; - struct dt_object *obj; - int rc = 0; + struct lquota_thread_info *qti = lquota_info(env); + __u64 key; + struct dt_object *obj; + struct obd_dqblk *dqblk = &oqctl->qc_dqblk; + int rc; ENTRY; if (oqctl->qc_cmd != Q_GETOQUOTA) { /* as in many other places, dev->dd_lu_dev.ld_obd->obd_name - * point to a valid obd_name, to be fixed in LU-1574 */ + * point to an invalid obd_name, to be fixed in LU-1574 */ CERROR("%s: Unsupported quotactl command: %x\n", dev->dd_lu_dev.ld_obd->obd_name, oqctl->qc_cmd); RETURN(-EOPNOTSUPP); } - if (oqctl->qc_type == USRQUOTA) - obj = acct_obj_lookup(env, dev, ACCT_USER_OID); - else if (oqctl->qc_type == GRPQUOTA) - obj = acct_obj_lookup(env, dev, ACCT_GROUP_OID); - else + if (oqctl->qc_type != USRQUOTA && oqctl->qc_type != GRPQUOTA) /* no support for directory quota yet */ RETURN(-EOPNOTSUPP); + /* qc_id is a 32-bit field while a key has 64 bits */ + key = oqctl->qc_id; + + /* Step 1: collect accounting information */ + + obj = acct_obj_lookup(env, dev, oqctl->qc_type); if (IS_ERR(obj)) RETURN(-EOPNOTSUPP); if (obj->do_index_ops == NULL) GOTO(out, rc = -EINVAL); - /* qc_id is a 32-bit field while a key has 64 bits */ - key = oqctl->qc_id; - /* lookup record storing space accounting information for this ID */ - rc = dt_lookup(env, obj, (struct dt_rec *)&rec, (struct dt_key *)&key, - BYPASS_CAPA); + rc = dt_lookup(env, obj, (struct dt_rec *)&qti->qti_acct_rec, + (struct dt_key *)&key, BYPASS_CAPA); if (rc < 0) GOTO(out, rc); memset(&oqctl->qc_dqblk, 0, sizeof(struct obd_dqblk)); - oqctl->qc_dqblk.dqb_curspace = rec.bspace; - oqctl->qc_dqblk.dqb_curinodes = rec.ispace; - oqctl->qc_dqblk.dqb_valid = QIF_USAGE; - /* TODO: must set {hard,soft}limit and grace time */ + dqblk->dqb_curspace = qti->qti_acct_rec.bspace; + dqblk->dqb_curinodes = qti->qti_acct_rec.ispace; + dqblk->dqb_valid = QIF_USAGE; + + lu_object_put(env, &obj->do_lu); + + /* Step 2: collect enforcement information */ - EXIT; + obj = quota_obj_lookup(env, dev, oqctl->qc_type); + if (IS_ERR(obj)) + RETURN(0); + if (obj->do_index_ops == NULL) + GOTO(out, rc = 0); + + memset(&qti->qti_slv_rec, 0, sizeof(qti->qti_slv_rec)); + /* lookup record storing enforcement information for this ID */ + rc = dt_lookup(env, obj, (struct dt_rec *)&qti->qti_slv_rec, + (struct dt_key *)&key, BYPASS_CAPA); + if (rc < 0 && rc != -ENOENT) + GOTO(out, rc = 0); + + if (lu_device_is_md(dev->dd_lu_dev.ld_site->ls_top_dev)) { + dqblk->dqb_ihardlimit = qti->qti_slv_rec.qsr_granted; + dqblk->dqb_bhardlimit = 0; + } else { + dqblk->dqb_ihardlimit = 0; + dqblk->dqb_bhardlimit = qti->qti_slv_rec.qsr_granted; + } + dqblk->dqb_valid |= QIF_LIMITS; + + GOTO(out, rc = 0); out: lu_object_put(env, &obj->do_lu); return rc; } EXPORT_SYMBOL(lquotactl_slv); + +static int __init init_lquota(void) +{ + int rc; + + /* call old quota module init function */ + rc = init_lustre_quota(); + if (rc) + return rc; + + /* new quota initialization */ + lquota_key_init_generic(&lquota_thread_key, NULL); + lu_context_key_register(&lquota_thread_key); + + return 0; +} + +static void exit_lquota(void) +{ + /* call old quota module exit function */ + exit_lustre_quota(); + + lu_context_key_degister(&lquota_thread_key); +} + +MODULE_AUTHOR("Intel, Inc. "); +MODULE_DESCRIPTION("Lustre Quota"); +MODULE_LICENSE("GPL"); + +cfs_module(lquota, "2.4.0", init_lquota, exit_lquota); diff --git a/lustre/quota/quota_interface.c b/lustre/quota/quota_interface.c index 3eab618..53d450c 100644 --- a/lustre/quota/quota_interface.c +++ b/lustre/quota/quota_interface.c @@ -770,7 +770,7 @@ quota_interface_t filter_quota_interface = { cfs_proc_dir_entry_t *lquota_type_proc_dir = NULL; -static int __init init_lustre_quota(void) +int init_lustre_quota(void) { int rc = 0; @@ -793,7 +793,7 @@ static int __init init_lustre_quota(void) return 0; } -static void /*__exit*/ exit_lustre_quota(void) +void exit_lustre_quota(void) { PORTAL_SYMBOL_UNREGISTER(filter_quota_interface); PORTAL_SYMBOL_UNREGISTER(mds_quota_interface); @@ -804,12 +804,6 @@ static void /*__exit*/ exit_lustre_quota(void) lprocfs_remove(&lquota_type_proc_dir); } -MODULE_AUTHOR("Sun Microsystems, Inc. "); -MODULE_DESCRIPTION("Lustre Quota"); -MODULE_LICENSE("GPL"); - -cfs_module(lquota, "1.0.0", init_lustre_quota, exit_lustre_quota); - EXPORT_SYMBOL(mds_quota_interface); EXPORT_SYMBOL(filter_quota_interface); #endif /* __KERNEL */ diff --git a/lustre/utils/wirecheck.c b/lustre/utils/wirecheck.c index 95216bf..79655ac 100644 --- a/lustre/utils/wirecheck.c +++ b/lustre/utils/wirecheck.c @@ -737,6 +737,23 @@ check_obd_quotactl(void) CHECK_DEFINE_X(Q_GETOINFO); CHECK_DEFINE_X(Q_GETOQUOTA); CHECK_DEFINE_X(Q_FINVALIDATE); + + BLANK_LINE(); + CHECK_STRUCT(lquota_acct_rec); + CHECK_MEMBER(lquota_acct_rec, bspace); + CHECK_MEMBER(lquota_acct_rec, ispace); + + BLANK_LINE(); + CHECK_STRUCT(lquota_glb_rec); + CHECK_MEMBER(lquota_glb_rec, qbr_hardlimit); + CHECK_MEMBER(lquota_glb_rec, qbr_softlimit); + CHECK_MEMBER(lquota_glb_rec, qbr_time); + CHECK_MEMBER(lquota_glb_rec, qbr_granted); + + BLANK_LINE(); + CHECK_STRUCT(lquota_slv_rec); + CHECK_MEMBER(lquota_slv_rec, qsr_granted); + } static void diff --git a/lustre/utils/wiretest.c b/lustre/utils/wiretest.c index 9e67f2c..b1c8c5d 100644 --- a/lustre/utils/wiretest.c +++ b/lustre/utils/wiretest.c @@ -1638,6 +1638,46 @@ void lustre_assert_wire_constants(void) LASSERTF(Q_FINVALIDATE == 0x800104, "found 0x%.8x\n", Q_FINVALIDATE); + /* Checks for struct lquota_acct_rec */ + LASSERTF((int)sizeof(struct lquota_acct_rec) == 16, "found %lld\n", + (long long)(int)sizeof(struct lquota_acct_rec)); + LASSERTF((int)offsetof(struct lquota_acct_rec, bspace) == 0, "found %lld\n", + (long long)(int)offsetof(struct lquota_acct_rec, bspace)); + LASSERTF((int)sizeof(((struct lquota_acct_rec *)0)->bspace) == 8, "found %lld\n", + (long long)(int)sizeof(((struct lquota_acct_rec *)0)->bspace)); + LASSERTF((int)offsetof(struct lquota_acct_rec, ispace) == 8, "found %lld\n", + (long long)(int)offsetof(struct lquota_acct_rec, ispace)); + LASSERTF((int)sizeof(((struct lquota_acct_rec *)0)->ispace) == 8, "found %lld\n", + (long long)(int)sizeof(((struct lquota_acct_rec *)0)->ispace)); + + /* Checks for struct lquota_glb_rec */ + LASSERTF((int)sizeof(struct lquota_glb_rec) == 32, "found %lld\n", + (long long)(int)sizeof(struct lquota_glb_rec)); + LASSERTF((int)offsetof(struct lquota_glb_rec, qbr_hardlimit) == 0, "found %lld\n", + (long long)(int)offsetof(struct lquota_glb_rec, qbr_hardlimit)); + LASSERTF((int)sizeof(((struct lquota_glb_rec *)0)->qbr_hardlimit) == 8, "found %lld\n", + (long long)(int)sizeof(((struct lquota_glb_rec *)0)->qbr_hardlimit)); + LASSERTF((int)offsetof(struct lquota_glb_rec, qbr_softlimit) == 8, "found %lld\n", + (long long)(int)offsetof(struct lquota_glb_rec, qbr_softlimit)); + LASSERTF((int)sizeof(((struct lquota_glb_rec *)0)->qbr_softlimit) == 8, "found %lld\n", + (long long)(int)sizeof(((struct lquota_glb_rec *)0)->qbr_softlimit)); + LASSERTF((int)offsetof(struct lquota_glb_rec, qbr_time) == 16, "found %lld\n", + (long long)(int)offsetof(struct lquota_glb_rec, qbr_time)); + LASSERTF((int)sizeof(((struct lquota_glb_rec *)0)->qbr_time) == 8, "found %lld\n", + (long long)(int)sizeof(((struct lquota_glb_rec *)0)->qbr_time)); + LASSERTF((int)offsetof(struct lquota_glb_rec, qbr_granted) == 24, "found %lld\n", + (long long)(int)offsetof(struct lquota_glb_rec, qbr_granted)); + LASSERTF((int)sizeof(((struct lquota_glb_rec *)0)->qbr_granted) == 8, "found %lld\n", + (long long)(int)sizeof(((struct lquota_glb_rec *)0)->qbr_granted)); + + /* Checks for struct lquota_slv_rec */ + LASSERTF((int)sizeof(struct lquota_slv_rec) == 8, "found %lld\n", + (long long)(int)sizeof(struct lquota_slv_rec)); + LASSERTF((int)offsetof(struct lquota_slv_rec, qsr_granted) == 0, "found %lld\n", + (long long)(int)offsetof(struct lquota_slv_rec, qsr_granted)); + LASSERTF((int)sizeof(((struct lquota_slv_rec *)0)->qsr_granted) == 8, "found %lld\n", + (long long)(int)sizeof(((struct lquota_slv_rec *)0)->qsr_granted)); + /* Checks for struct niobuf_remote */ LASSERTF((int)sizeof(struct niobuf_remote) == 16, "found %lld\n", (long long)(int)sizeof(struct niobuf_remote));