+ * Adjust quota space (by acquiring or releasing) hold by the quota slave.
+ * This function is called after each quota request completion and during
+ * reintegration in order to report usage or re-acquire quota locks.
+ * Space adjustment is aborted if there is already a quota request in flight
+ * for this ID.
+ *
+ * \param env - the environment passed by the caller
+ * \param lqe - is the qid entry to be processed
+ *
+ * \retval 0 on success, appropriate errors on failure
+ */
+int qsd_adjust(const struct lu_env *env, struct lquota_entry *lqe)
+{
+ struct qsd_thread_info *qti = qsd_info(env);
+ struct quota_body *qbody = &qti->qti_body;
+ struct qsd_instance *qsd;
+ struct qsd_qtype_info *qqi;
+ int rc;
+ bool intent = false;
+ ENTRY;
+
+ memset(qbody, 0, sizeof(*qbody));
+ rc = qsd_ready(lqe, &qbody->qb_glb_lockh);
+ if (rc)
+ RETURN(rc);
+
+ qqi = lqe2qqi(lqe);
+ qsd = qqi->qqi_qsd;
+
+ lqe_write_lock(lqe);
+
+ /* fill qb_count & qb_flags */
+ if (!qsd_calc_adjust(lqe, qbody)) {
+ lqe_write_unlock(lqe);
+ LQUOTA_DEBUG(lqe, "No adjust required");
+ RETURN(0);
+ }
+
+ /* only 1 quota request in flight for a given ID is allowed */
+ rc = qsd_request_enter(lqe);
+ if (rc) {
+ /* already a request in flight, space adjustment will be run
+ * again on request completion */
+ lqe_write_unlock(lqe);
+ RETURN(0);
+ }
+
+ if (req_is_rel(qbody->qb_flags))
+ lqe->lqe_pending_rel = qbody->qb_count;
+ lustre_handle_copy(&qti->qti_lockh, &lqe->lqe_lockh);
+ lqe_write_unlock(lqe);
+
+ /* hold a refcount until completion */
+ lqe_getref(lqe);
+
+ /* fill other quota body fields */
+ qbody->qb_fid = qqi->qqi_fid;
+ qbody->qb_id = lqe->lqe_id;
+
+ if (req_is_acq(qbody->qb_flags) || req_is_preacq(qbody->qb_flags)) {
+ /* check whether we own a valid lock for this ID */
+ rc = qsd_id_lock_match(&qti->qti_lockh, &qbody->qb_lockh);
+ if (rc) {
+ memset(&qti->qti_lockh, 0, sizeof(qti->qti_lockh));
+ if (req_is_preacq(qbody->qb_flags)) {
+ if (req_has_rep(qbody->qb_flags))
+ /* still want to report usage */
+ qbody->qb_flags = QUOTA_DQACQ_FL_REPORT;
+ else
+ /* no pre-acquire if no per-ID lock */
+ GOTO(out, rc = -ENOLCK);
+ } else {
+ /* no lock found, should use intent */
+ intent = true;
+ }
+ } else if (req_is_acq(qbody->qb_flags) &&
+ qbody->qb_count == 0) {
+ /* found cached lock, no need to acquire */
+ GOTO(out, rc = 0);
+ }
+ } else {
+ /* release and report don't need a per-ID lock */
+ memset(&qti->qti_lockh, 0, sizeof(qti->qti_lockh));
+ }
+
+ if (!intent) {
+ rc = qsd_send_dqacq(env, qsd->qsd_exp, qbody, false,
+ qsd_req_completion, qqi, &qti->qti_lockh,
+ lqe);
+ } else {
+ union ldlm_wire_lvb *lvb;
+
+ OBD_ALLOC_PTR(lvb);
+ if (lvb == NULL)
+ GOTO(out, rc = -ENOMEM);
+
+ rc = qsd_intent_lock(env, qsd->qsd_exp, qbody, false,
+ IT_QUOTA_DQACQ, qsd_req_completion,
+ qqi, lvb, (void *)lqe);
+ }
+ /* the completion function will be called by qsd_send_dqacq or
+ * qsd_intent_lock */
+ RETURN(rc);
+out:
+ qsd_req_completion(env, qqi, qbody, NULL, &qti->qti_lockh, NULL, lqe,
+ rc);
+ return rc;
+}
+
+/**