+ EXIT;
+out:
+ if (rc) {
+ qsd_fini(env, qsd);
+ return ERR_PTR(rc);
+ }
+ RETURN(qsd);
+}
+EXPORT_SYMBOL(qsd_init);
+
+/*
+ * Initialize on-disk structures in order to manage quota enforcement for
+ * the target associated with the qsd instance \qsd and starts the reintegration
+ * procedure for each quota type as soon as possible.
+ * The last step of the reintegration will be completed once qsd_start() is
+ * called, at which points the space reconciliation with the master will be
+ * executed.
+ * This function must be called when the server stack is fully configured,
+ * typically when ->ldo_prepare is called across the stack.
+ *
+ * \param env - the environment passed by the caller
+ * \param qsd - is qsd_instance to prepare
+ *
+ * \retval - 0 on success, appropriate error on failure
+ */
+int qsd_prepare(const struct lu_env *env, struct qsd_instance *qsd)
+{
+ struct qsd_thread_info *qti = qsd_info(env);
+ int qtype, rc = 0;
+ ENTRY;
+
+ LASSERT(qsd != NULL);
+
+ cfs_read_lock(&qsd->qsd_lock);
+ if (qsd->qsd_prepared) {
+ CERROR("%s: qsd instance already prepared\n", qsd->qsd_svname);
+ rc = -EALREADY;
+ }
+ cfs_read_unlock(&qsd->qsd_lock);
+ if (rc)
+ RETURN(rc);
+
+ /* Record whether this qsd instance is managing quota enforcement for a
+ * MDT (i.e. inode quota) or OST (block quota) */
+ if (lu_device_is_md(qsd->qsd_dev->dd_lu_dev.ld_site->ls_top_dev)) {
+ qsd->qsd_is_md = true;
+ qsd->qsd_sync_threshold = LQUOTA_LEAST_QUNIT(LQUOTA_RES_MD);
+ } else {
+ qsd->qsd_sync_threshold = LQUOTA_LEAST_QUNIT(LQUOTA_RES_DT);
+ }
+
+ /* look-up on-disk directory for the quota slave */
+ qsd->qsd_root = lquota_disk_dir_find_create(env, qsd->qsd_dev, NULL,
+ QSD_DIR);
+ if (IS_ERR(qsd->qsd_root)) {
+ rc = PTR_ERR(qsd->qsd_root);
+ qsd->qsd_root = NULL;
+ CERROR("%s: failed to create quota slave root dir (%d)\n",
+ qsd->qsd_svname, rc);
+ RETURN(rc);
+ }