+
+struct ofd_grant_cb {
+ /* commit callback structure */
+ struct dt_txn_commit_cb ogc_cb;
+ /* export associated with the bulk write */
+ struct obd_export *ogc_exp;
+ /* pending grant to be released */
+ unsigned long ogc_granted;
+};
+
+/**
+ * Callback function for grant releasing
+ *
+ * Release grant space reserved by the client node.
+ *
+ * \param[in] env execution environment
+ * \param[in] th transaction handle
+ * \param[in] cb callback data
+ * \param[in] err error code
+ */
+static void ofd_grant_commit_cb(struct lu_env *env, struct thandle *th,
+ struct dt_txn_commit_cb *cb, int err)
+{
+ struct ofd_grant_cb *ogc;
+
+ ogc = container_of(cb, struct ofd_grant_cb, ogc_cb);
+
+ ofd_grant_commit(ogc->ogc_exp, ogc->ogc_granted, err);
+ class_export_cb_put(ogc->ogc_exp);
+ OBD_FREE_PTR(ogc);
+}
+
+/**
+ * Add callback for grant releasing
+ *
+ * Register a commit callback to release grant space.
+ *
+ * \param[in] th transaction handle
+ * \param[in] exp OBD export of client
+ * \param[in] granted amount of grant space to be released upon commit
+ *
+ * \retval 0 on successful callback adding
+ * \retval negative value on error
+ */
+int ofd_grant_commit_cb_add(struct thandle *th, struct obd_export *exp,
+ unsigned long granted)
+{
+ struct ofd_grant_cb *ogc;
+ struct dt_txn_commit_cb *dcb;
+ int rc;
+ ENTRY;
+
+ OBD_ALLOC_PTR(ogc);
+ if (ogc == NULL)
+ RETURN(-ENOMEM);
+
+ ogc->ogc_exp = class_export_cb_get(exp);
+ ogc->ogc_granted = granted;
+
+ dcb = &ogc->ogc_cb;
+ dcb->dcb_func = ofd_grant_commit_cb;
+ INIT_LIST_HEAD(&dcb->dcb_linkage);
+ strlcpy(dcb->dcb_name, "ofd_grant_commit_cb", sizeof(dcb->dcb_name));
+
+ rc = dt_trans_cb_add(th, dcb);
+ if (rc) {
+ class_export_cb_put(ogc->ogc_exp);
+ OBD_FREE_PTR(ogc);
+ }
+
+ RETURN(rc);
+}