Whamcloud - gitweb
LU-1842 quota: define quota records for glb/slv indexes
authorJohann Lombardi <johann@whamcloud.com>
Thu, 6 Sep 2012 10:54:13 +0000 (12:54 +0200)
committerOleg Drokin <green@whamcloud.com>
Mon, 10 Sep 2012 06:56:47 +0000 (02:56 -0400)
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 <johann@whamcloud.com>
Change-Id: I2b261bd8433a5e6bd64c2de2710bca32bf606122
Reviewed-on: http://review.whamcloud.com/3886
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: Hudson
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Fan Yong <yong.fan@whamcloud.com>
Reviewed-by: Niu Yawei <niu@whamcloud.com>
13 files changed:
lustre/include/dt_object.h
lustre/include/lquota.h
lustre/include/lustre/lustre_idl.h
lustre/obdclass/dt_object.c
lustre/osd-ldiskfs/osd_quota.c
lustre/osd-zfs/osd_quota.c
lustre/ptlrpc/wiretest.c
lustre/quota/lproc_quota.c
lustre/quota/lquota_internal.h
lustre/quota/lquota_lib.c
lustre/quota/quota_interface.c
lustre/utils/wirecheck.c
lustre/utils/wiretest.c

index c57fc00..5455194 100644 (file)
@@ -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.
index 13d1021..9f2e3e5 100644 (file)
 #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
index 41b1af1..02a4e23 100644 (file)
@@ -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 */
index 052cb4e..c231814 100644 (file)
@@ -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);
index c39f829..1d26b48 100644 (file)
@@ -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;
 
index 68e8dd5..1f9e2d2 100644 (file)
@@ -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;
index 443c518..1501413 100644 (file)
@@ -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));
index b385d07..6c8a5c8 100644 (file)
@@ -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) {
index b39f633..22fc7a2 100644 (file)
 
 #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 */
index 0f5d984..51a0c49 100644 (file)
  * GPL HEADER END
  */
 /*
- * Copyright (c) 2011, 2012, Whamcloud, Inc.
+ * Copyright (c) 2011, 2012, Intel, Inc.
  * Use is subject to license terms.
  *
- * Author: Johann Lombardi <johann@whamcloud.com>
- * Author: Niu    Yawei    <niu@whamcloud.com>
+ * Author: Johann Lombardi <johann.lombardi@intel.com>
+ * Author: Niu    Yawei    <yawei.niu@intel.com>
  */
 
 #ifndef EXPORT_SYMTAB
 
 #define DEBUG_SUBSYSTEM S_LQUOTA
 
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
 #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. <http://www.intel.com/>");
+MODULE_DESCRIPTION("Lustre Quota");
+MODULE_LICENSE("GPL");
+
+cfs_module(lquota, "2.4.0", init_lquota, exit_lquota);
index 3eab618..53d450c 100644 (file)
@@ -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. <http://www.lustre.org/>");
-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 */
index 95216bf..79655ac 100644 (file)
@@ -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
index 9e67f2c..b1c8c5d 100644 (file)
@@ -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));