* GPL HEADER END
*/
/*
- * Copyright (c) 2012 Intel, Inc.
+ * Copyright (c) 2012, 2017, Intel Corporation.
* Use is subject to license terms.
*
* Author: Johann Lombardi <johann.lombardi@intel.com>
* The QMT device is currently set up by the MDT and should probably be moved
* to a separate target in the future. Meanwhile, the MDT forwards all quota
* requests to the QMT via a list of request handlers (see struct qmt_handlers
- * in lquota.h). The QMT also borrows the LDLM namespace from the MDT.
+ * in lustre_quota.h). The QMT also borrows the LDLM namespace from the MDT.
*
* To bring up a QMT device, the following steps must be completed:
*
* mdt_quota_init() for more details.
*/
-#ifndef EXPORT_SYMTAB
-# define EXPORT_SYMTAB
-#endif
-
#define DEBUG_SUBSYSTEM S_LQUOTA
#include <obd_class.h>
LASSERT(qmt != NULL);
CDEBUG(D_QUOTA, "%s: initiating QMT shutdown\n", qmt->qmt_svname);
+ qmt->qmt_stopping = true;
+
+ /* kill pool instances, if any */
+ qmt_pool_fini(env, qmt);
+
+ /* remove qmt proc entry */
+ if (qmt->qmt_proc != NULL && !IS_ERR(qmt->qmt_proc)) {
+ lprocfs_remove(&qmt->qmt_proc);
+ qmt->qmt_proc = NULL;
+ }
+
+ /* stop rebalance thread */
+ if (!qmt->qmt_child->dd_rdonly)
+ qmt_stop_reba_thread(qmt);
/* disconnect from OSD */
if (qmt->qmt_child_exp != NULL) {
obd_disconnect(qmt->qmt_child_exp);
qmt->qmt_child_exp = NULL;
- qmt->qmt_child = NULL;
+ qmt->qmt_child = NULL;
}
+ /* clear references to MDT namespace */
+ ld->ld_obd->obd_namespace = NULL;
+ qmt->qmt_ns = NULL;
+
RETURN(NULL);
}
/* initialize site (although it isn't used anywhere) and lu_device
* pointer to next device */
qmt->qmt_child = lu2dt_dev(qmt->qmt_child_exp->exp_obd->obd_lu_dev);
- ld->ld_site = qmt->qmt_child_exp->exp_obd->obd_lu_dev->ld_site;
+ ld->ld_site = qmt->qmt_child_exp->exp_obd->obd_lu_dev->ld_site;
EXIT;
out:
if (data)
struct lu_device_type *ldt, struct lustre_cfg *cfg)
{
struct lu_device *ld = qmt2lu_dev(qmt);
- struct obd_device *obd;
+ struct obd_device *obd, *mdt_obd;
+ struct obd_type *type;
+ char *svname = lustre_cfg_string(cfg, 0);
int rc;
ENTRY;
+ if (svname == NULL)
+ RETURN(-EINVAL);
+
/* record who i am, it might be useful ... */
- strncpy(qmt->qmt_svname, lustre_cfg_string(cfg, 0),
- sizeof(qmt->qmt_svname) - 1);
+ rc = strlcpy(qmt->qmt_svname, svname, sizeof(qmt->qmt_svname));
+ if (rc >= sizeof(qmt->qmt_svname))
+ RETURN(-E2BIG);
/* look-up the obd_device associated with the qmt */
obd = class_name2obd(qmt->qmt_svname);
obd->obd_lu_dev = ld;
ld->ld_obd = obd;
+ /* look-up the parent MDT to steal its ldlm namespace ... */
+ mdt_obd = class_name2obd(lustre_cfg_string(cfg, 2));
+ if (mdt_obd == NULL)
+ RETURN(-ENOENT);
+
+ /* borrow MDT namespace. kind of a hack until we have our own namespace
+ * & service threads */
+ LASSERT(mdt_obd->obd_namespace != NULL);
+ obd->obd_namespace = mdt_obd->obd_namespace;
+ qmt->qmt_ns = obd->obd_namespace;
+
/* connect to backend osd device */
rc = qmt_connect_to_osd(env, qmt, cfg);
if (rc)
GOTO(out, rc);
+ /* set up and start rebalance thread */
+ thread_set_flags(&qmt->qmt_reba_thread, SVC_STARTING);
+ init_waitqueue_head(&qmt->qmt_reba_thread.t_ctl_waitq);
+ INIT_LIST_HEAD(&qmt->qmt_reba_list);
+ spin_lock_init(&qmt->qmt_reba_lock);
+ if (!qmt->qmt_child->dd_rdonly) {
+ rc = qmt_start_reba_thread(qmt);
+ if (rc) {
+ CERROR("%s: failed to start rebalance thread (%d)\n",
+ qmt->qmt_svname, rc);
+ GOTO(out, rc);
+ }
+ }
+
+ /* at the moment there is no linkage between lu_type and obd_type, so
+ * we lookup obd_type this way */
+ type = class_search_type(LUSTRE_QMT_NAME);
+ LASSERT(type != NULL);
+
+ /* register proc directory associated with this qmt */
+ qmt->qmt_proc = lprocfs_register(qmt->qmt_svname, type->typ_procroot,
+ NULL, NULL);
+ if (IS_ERR(qmt->qmt_proc)) {
+ rc = PTR_ERR(qmt->qmt_proc);
+ CERROR("%s: failed to create qmt proc entry (%d)\n",
+ qmt->qmt_svname, rc);
+ GOTO(out, rc);
+ }
+
+ /* initialize pool configuration */
+ rc = qmt_pool_init(env, qmt);
+ if (rc)
+ GOTO(out, rc);
EXIT;
out:
if (rc)
struct lu_device *parent,
struct lu_device *ld)
{
- return 0;
+ struct qmt_device *qmt = lu2qmt_dev(ld);
+ struct dt_object *qmt_root;
+ int rc;
+ ENTRY;
+
+ /* initialize quota master root directory where all index files will be
+ * stored */
+ qmt_root = lquota_disk_dir_find_create(env, qmt->qmt_child, NULL,
+ QMT_DIR);
+ if (IS_ERR(qmt_root)) {
+ rc = PTR_ERR(qmt_root);
+ CERROR("%s: failed to create master quota directory (%d)\n",
+ qmt->qmt_svname, rc);
+ RETURN(rc);
+ }
+
+ /* initialize on-disk indexes associated with each pool */
+ rc = qmt_pool_prepare(env, qmt, qmt_root);
+
+ dt_object_put(env, qmt_root);
+ RETURN(rc);
}
/*
int rc;
ENTRY;
- rc = class_register_type(&qmt_obd_ops, NULL, NULL, LUSTRE_QMT_NAME,
- &qmt_device_type);
+ rc = class_register_type(&qmt_obd_ops, NULL, true, NULL,
+ LUSTRE_QMT_NAME, &qmt_device_type);
RETURN(rc);
}