+ * Delete the quota setting of the specified quota ID
+ *
+ * \param env - is the environment passed by the caller
+ * \param qmt - is the quota master target
+ * \param restype - is the pool type, either block (i.e. LQUOTA_RES_DT) or
+ * inode (i.e. LQUOTA_RES_MD)
+ * \param qtype - is the quota type
+ * \param qid - is the quota indentifier for which we want to delete its
+ * quota settings.
+ */
+static int qmt_delete_qid(const struct lu_env *env, struct qmt_device *qmt,
+ __u8 restype, __u8 qtype, __u64 qid)
+{
+ struct qmt_thread_info *qti = qmt_info(env);
+ union lquota_id *quota_id = &qti->qti_id;
+ struct thandle *th = NULL;
+ struct qmt_pool_info *qpi = NULL;
+ struct lquota_entry *lqe = NULL;
+ __u64 ver = 0;
+ int rc;
+
+ ENTRY;
+
+ quota_id->qid_uid = qid;
+ lqe = qmt_pool_lqe_lookup(env, qmt, restype, qtype, quota_id, NULL);
+ if (IS_ERR(lqe))
+ RETURN(PTR_ERR(lqe));
+
+ lqe_write_lock(lqe);
+
+ qpi = qmt_pool_lookup_glb(env, qmt, restype);
+ if (IS_ERR(qpi))
+ GOTO(out, rc = -ENOMEM);
+
+ th = qmt_trans_start(env, lqe);
+ if (IS_ERR(th))
+ GOTO(out, rc = PTR_ERR(th));
+
+ rc = lquota_disk_delete(env, th,
+ qpi->qpi_glb_obj[qtype], qid, &ver);
+
+ dt_trans_stop(env, qmt->qmt_child, th);
+
+ if (rc == 0) {
+ lqe_set_deleted(lqe);
+ qmt_glb_lock_notify(env, lqe, ver);
+ } else if (rc == -ENOENT) {
+ rc = 0;
+ }
+
+out:
+ if (!IS_ERR_OR_NULL(qpi))
+ qpi_putref(env, qpi);
+
+ lqe_write_unlock(lqe);
+ lqe_putref(lqe);
+
+ RETURN(rc);
+}
+
+static int qmt_reset_slv_cb(const struct lu_env *env, struct lu_fid *glb_fid,
+ char *slv_name, struct lu_fid *slv_fid, void *arg)
+{
+ struct qmt_device *qmt = (struct qmt_device *)arg;
+ struct qmt_thread_info *qti = qmt_info(env);
+ struct dt_object *slv_obj = NULL;
+ struct lquota_slv_rec rec;
+ struct thandle *th = NULL;
+ int rc;
+
+ slv_obj = dt_locate(env, qmt->qmt_child, slv_fid);
+ if (IS_ERR(slv_obj))
+ GOTO(out, rc = PTR_ERR(slv_obj));
+
+ if (slv_obj->do_index_ops == NULL) {
+ rc = slv_obj->do_ops->do_index_try(env, slv_obj,
+ &dt_quota_slv_features);
+ if (rc) {
+ CERROR("%s: fail to setup slave idx for %s: rc = %d\n",
+ qmt->qmt_child->dd_lu_dev.ld_obd->obd_name,
+ slv_name, rc);
+ GOTO(out, rc);
+ }
+ }
+
+ th = qmt_trans_start(env, qti_lqes(env)[0]);
+ if (IS_ERR(th))
+ GOTO(out, rc = PTR_ERR(th));
+
+ rec.qsr_granted = 0;
+ rc = lquota_disk_write(env, th, slv_obj, &qti->qti_id,
+ (struct dt_rec *)&rec, 0, NULL);
+ if (rc)
+ CERROR("%s: failed to reset slave grant for %s: rc = %d\n",
+ qmt->qmt_child->dd_lu_dev.ld_obd->obd_name, slv_name,
+ rc);
+out:
+ if (!IS_ERR_OR_NULL(th))
+ dt_trans_stop(env, qmt->qmt_child, th);
+
+ if (slv_obj != NULL)
+ dt_object_put(env, slv_obj);
+ return 0;
+}
+
+/*
+ * Reset the quota of the quota ID, it will reset the soft/hard limit and grant
+ *
+ * \param env - is the environment passed by the caller
+ * \param qmt - is the quota master target
+ * \param restype - is the pool type, either block (i.e. LQUOTA_RES_DT) or
+ * inode (i.e. LQUOTA_RES_MD)
+ * \param qtype - is the quota type
+ * \param qid - is the quota indentifier for which we want to delete its
+ * quota settings.
+ */
+static int qmt_reset_qid(const struct lu_env *env, struct qmt_device *qmt,
+ __u8 restype, __u8 qtype, __u64 qid)
+{
+ struct qmt_thread_info *qti = qmt_info(env);
+ union lquota_id *quota_id = &qti->qti_id;
+ struct qmt_pool_info *qpi = NULL;
+ struct lquota_entry *lqe = NULL;
+ struct thandle *th = NULL;
+ __u64 softlimit = 0, hardlimit = 0;
+ __u64 ver = 0;
+ int rc;
+
+ ENTRY;
+
+ quota_id->qid_uid = qid;
+ lqe = qmt_pool_lqe_lookup(env, qmt, restype, qtype, quota_id, NULL);
+ if (IS_ERR(lqe))
+ RETURN(PTR_ERR(lqe));
+
+ lqe_write_lock(lqe);
+
+ qpi = qmt_pool_lookup_glb(env, qmt, restype);
+ if (IS_ERR(qpi))
+ GOTO(out, rc = -ENOMEM);
+
+ th = qmt_trans_start(env, lqe);
+ if (IS_ERR(th))
+ GOTO(out, rc = PTR_ERR(th));
+
+ softlimit = lqe->lqe_softlimit;
+ hardlimit = lqe->lqe_hardlimit;
+
+ lqe->lqe_softlimit = 0;
+ lqe->lqe_hardlimit = 0;
+ lqe->lqe_granted = 0;
+ lqe->lqe_edquot = 0;
+ lqe->lqe_qunit = 0;
+ lqe->lqe_is_default = 0;
+ lqe->lqe_is_deleted = 0;
+ lqe->lqe_is_reset = 1;
+ rc = qmt_glb_write(env, th, lqe, LQUOTA_BUMP_VER, &ver);
+ if (rc)
+ LQUOTA_ERROR(lqe, "failed to write quota global rec\n");
+ dt_trans_stop(env, qmt->qmt_child, th);
+ if (rc)
+ GOTO(out, rc);
+
+ lquota_generate_fid(&qti->qti_fid, restype, qtype);
+ qti_lqes(env)[0] = lqe;
+ lquota_disk_for_each_slv(env, qpi->qpi_root, &qti->qti_fid,
+ qmt_reset_slv_cb, qmt);
+
+ qmt_glb_lock_notify(env, lqe, ver);
+
+out:
+ if (rc) {
+ if (softlimit != 0)
+ lqe->lqe_softlimit = softlimit;
+ if (hardlimit != 0)
+ lqe->lqe_hardlimit = hardlimit;
+ lqe->lqe_is_reset = 0;
+ }
+
+ if (!IS_ERR_OR_NULL(qpi))
+ qpi_putref(env, qpi);
+
+ lqe_write_unlock(lqe);
+ lqe_putref(lqe);
+
+ RETURN(rc);
+}
+/*