4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 021110-1307, USA
24 * Copyright (c) 2012, 2017, Intel Corporation.
25 * Use is subject to license terms.
27 * Author: Johann Lombardi <johann.lombardi@intel.com>
28 * Author: Niu Yawei <yawei.niu@intel.com>
31 #define DEBUG_SUBSYSTEM S_LQUOTA
33 #include "qsd_internal.h"
36 * Initialize qsd-specific fields of quota entry.
38 * \param lqe - is the quota entry to initialize
39 * \param arg - is the pointer to the qsd_qtype_info structure
41 static void qsd_lqe_init(struct lquota_entry *lqe, void *arg)
43 LASSERT(!lqe_is_master(lqe));
45 /* initialize slave parameters */
46 rwlock_init(&lqe->lqe_lock);
47 memset(&lqe->lqe_lockh, 0, sizeof(lqe->lqe_lockh));
48 lqe->lqe_pending_write = 0;
49 lqe->lqe_pending_req = 0;
50 init_waitqueue_head(&lqe->lqe_waiters);
52 lqe->lqe_nopreacq = false;
53 mutex_init(&lqe->lqe_glbl_data_lock);
57 * Update a slave quota entry. This is done by reading enforcement status from
58 * the copy of the global index and the amount the slave currenly owns
59 * for this user from the slave index copy.
61 * \param env - the environment passed by the caller
62 * \param lqe - is the quota entry to refresh
63 * \param arg - is the pointer to the qsd_qtype_info structure
64 * \param need_crt - needed to be compat with qmt_lqe_read
66 static int qsd_lqe_read(const struct lu_env *env, struct lquota_entry *lqe,
67 void *arg, bool need_crt)
69 struct qsd_thread_info *qti = qsd_info(env);
70 struct qsd_qtype_info *qqi = (struct qsd_qtype_info *)arg;
73 LASSERT(!lqe_is_master(lqe));
75 /* read record from global index copy to know whether quota is
76 * enforced for this user */
77 rc = lquota_disk_read(env, qqi->qqi_glb_obj, &lqe->lqe_id,
78 (struct dt_rec *)&qti->qti_glb_rec);
82 /* no such entry, assume quota isn't enforced for this user */
83 lqe->lqe_enforced = false;
86 if (lqe->lqe_id.qid_uid == 0) {
87 qqi->qqi_default_hardlimit =
88 qti->qti_glb_rec.qbr_hardlimit;
89 qqi->qqi_default_softlimit =
90 qti->qti_glb_rec.qbr_softlimit;
91 qqi->qqi_default_gracetime =
92 qti->qti_glb_rec.qbr_granted;
95 if (lqe->lqe_id.qid_uid != 0 &&
96 (LQUOTA_FLAG(qti->qti_glb_rec.qbr_time) &
98 lqe->lqe_is_reset = true;
100 if (lqe->lqe_id.qid_uid != 0 &&
101 (qti->qti_glb_rec.qbr_hardlimit != 0 ||
102 qti->qti_glb_rec.qbr_softlimit != 0))
103 lqe->lqe_enforced = true;
105 lqe->lqe_enforced = false;
108 LQUOTA_ERROR(lqe, "failed to read quota entry from global "
109 "index copy, rc:%d", rc);
113 if (lqe->lqe_id.qid_uid != 0 &&
115 (LQUOTA_FLAG(qti->qti_glb_rec.qbr_time) & LQUOTA_FLAG_DEFAULT &&
116 qti->qti_glb_rec.qbr_hardlimit == 0 &&
117 qti->qti_glb_rec.qbr_softlimit == 0))) {
118 struct lquota_entry *lqe_def;
119 union lquota_id qid = { {0} };
121 /* ensure the lqe storing the default quota setting loaded */
122 lqe_def = lqe_locate(env, qqi->qqi_site, &qid);
124 lqe->lqe_is_default = true;
126 if (qqi->qqi_default_hardlimit != 0 ||
127 qqi->qqi_default_softlimit != 0) {
128 LQUOTA_DEBUG(lqe, "enforced by default quota");
129 lqe->lqe_enforced = true;
132 if (!IS_ERR(lqe_def))
136 /* read record from slave index copy to find out how much space is
137 * currently owned by this slave */
138 rc = lquota_disk_read(env, qqi->qqi_slv_obj, &lqe->lqe_id,
139 (struct dt_rec *)&qti->qti_slv_rec);
142 lqe->lqe_granted = 0;
145 lqe->lqe_granted = qti->qti_slv_rec.qsr_granted;
148 LQUOTA_ERROR(lqe, "failed to read quota entry from slave "
149 "index copy, rc:%d", rc);
153 /* don't know what the qunit value is yet */
154 qsd_set_qunit(lqe, 0);
156 /* read current disk-usage from disk */
157 rc = qsd_refresh_usage(env, lqe);
161 LQUOTA_DEBUG(lqe, "successfully read from disk");
166 * Print lqe information for debugging.
168 * \param lqe - is the quota entry to debug
169 * \param arg - is the pointer to the qsd_qtype_info structure
170 * \param msgdata - debug message
171 * \param fmt - format of debug message
173 static void qsd_lqe_debug(struct lquota_entry *lqe, void *arg,
174 struct libcfs_debug_msg_data *msgdata,
175 struct va_format *vaf)
177 struct qsd_qtype_info *qqi = (struct qsd_qtype_info *)arg;
179 libcfs_debug_msg(msgdata,
180 "%pV qsd:%s qtype:%s id:%llu enforced:%d granted: %llu pending:%llu waiting:%llu req:%d usage: %llu qunit:%llu qtune:%llu edquot:%d default:%s\n",
182 qqi->qqi_qsd->qsd_svname, qtype_name(qqi->qqi_qtype),
183 lqe->lqe_id.qid_uid, lqe->lqe_enforced,
184 lqe->lqe_granted, lqe->lqe_pending_write,
185 lqe->lqe_waiting_write, lqe->lqe_pending_req,
186 lqe->lqe_usage, lqe->lqe_qunit, lqe->lqe_qtune,
187 lqe->lqe_edquot, lqe->lqe_is_default ? "yes" : "no");
191 * Vector of quota entry operations supported on the slave
193 const struct lquota_entry_operations qsd_lqe_ops = {
194 .lqe_init = qsd_lqe_init,
195 .lqe_read = qsd_lqe_read,
196 .lqe_debug = qsd_lqe_debug,
199 int qsd_write_version(const struct lu_env *env, struct qsd_qtype_info *qqi,
200 __u64 ver, bool global)
202 struct qsd_instance *qsd = qqi->qqi_qsd;
203 struct dt_object *obj = global ? qqi->qqi_glb_obj :
208 rc = lquota_disk_update_ver(env, qsd->qsd_dev, obj, ver);
212 qsd_bump_version(qqi, ver, global);
217 * Consult current disk space consumed by a given identifier.
219 * \param env - the environment passed by the caller
220 * \param qqi - is the pointer to the qsd_qtype_info structure associated
221 * with the identifier.
222 * \param lqe - is the quota entry associated with the identifier
224 int qsd_refresh_usage(const struct lu_env *env, struct lquota_entry *lqe)
226 struct qsd_thread_info *qti = qsd_info(env);
227 struct lquota_acct_rec *rec = &qti->qti_acct_rec;
228 struct qsd_qtype_info *qqi = lqe2qqi(lqe);
232 LASSERT(qqi->qqi_acct_obj);
234 /* read disk usage */
235 rc = lquota_disk_read(env, qqi->qqi_acct_obj, &lqe->lqe_id,
236 (struct dt_rec *)rec);
243 if (qqi->qqi_qsd->qsd_is_md)
244 lqe->lqe_usage = rec->ispace;
246 lqe->lqe_usage = toqb(rec->bspace);
249 LQUOTA_ERROR(lqe, "failed to read disk usage, rc:%d", rc);
253 LQUOTA_DEBUG(lqe, "disk usage: %llu", lqe->lqe_usage);
258 * Update slave or global index copy.
260 * \param env - the environment passed by the caller
261 * \param qqi - is the qsd_type_info structure managing the index to be
263 * \param qid - is the identifier for which we need to update the quota
265 * \param global - is set to true when updating the global index copy and to
266 * false for the slave index copy.
267 * \param ver - is the new version of the index. If equal to 0, the version
268 * of the index isn't changed
269 * \param rec - is the updated record to insert in the index file
271 int qsd_update_index(const struct lu_env *env, struct qsd_qtype_info *qqi,
272 union lquota_id *qid, bool global, __u64 ver, void *rec)
274 struct thandle *th = NULL;
275 struct dt_object *obj;
276 __u64 *new_verp = NULL;
281 obj = global ? qqi->qqi_glb_obj : qqi->qqi_slv_obj;
283 /* allocate transaction */
284 th = dt_trans_create(env, qqi->qqi_qsd->qsd_dev);
288 /* reserve enough credits to update record in index file */
289 rc = lquota_disk_declare_write(env, th, obj, qid);
293 /* start local transaction */
294 rc = dt_trans_start_local(env, qqi->qqi_qsd->qsd_dev, th);
299 /* Update record in global index copy */
300 struct lquota_glb_rec *glb_rec = (struct lquota_glb_rec *)rec;
302 CDEBUG(D_QUOTA, "%s: updating global index hardlimit: %llu, "
303 "softlimit: %llu for id %llu\n",
304 qqi->qqi_qsd->qsd_svname, glb_rec->qbr_hardlimit,
305 glb_rec->qbr_softlimit, qid->qid_uid);
307 /* Update record in slave index copy */
308 struct lquota_slv_rec *slv_rec = (struct lquota_slv_rec *)rec;
310 CDEBUG(D_QUOTA, "%s: update granted to %llu for id %llu"
311 "\n", qqi->qqi_qsd->qsd_svname, slv_rec->qsr_granted,
317 flags = LQUOTA_SET_VER;
320 /* write new record to index file */
321 rc = lquota_disk_write(env, th, obj, qid, (struct dt_rec *)rec, flags,
325 dt_trans_stop(env, qqi->qqi_qsd->qsd_dev, th);
327 CERROR("%s: failed to update %s index copy for id %llu, : rc = %d\n",
328 qqi->qqi_qsd->qsd_svname,
329 global ? "global" : "slave", qid->qid_uid, rc);
330 else if (flags == LQUOTA_SET_VER)
331 qsd_bump_version(qqi, ver, global);
336 * Update in-memory lquota entry with new quota setting from record \rec.
337 * The record can either be a global record (i.e. lquota_glb_rec) or a slave
338 * index record (i.e. lquota_slv_rec). In the former case, \global should be
341 * \param env - the environment passed by the caller
342 * \param lqe - is the quota entry associated with the identifier
343 * \param global - is set to true when updating the record is of type
344 * lquota_glb_rec. Otherwise, it is a lquota_slv_rec record.
345 * \param rec - is the updated record received from the master.
347 int qsd_update_lqe(const struct lu_env *env, struct lquota_entry *lqe,
348 bool global, void *rec)
352 LASSERT(lqe != NULL);
353 LASSERT(!lqe_is_master(lqe));
355 /* updating lqe is always serialized, no locking needed. */
357 struct lquota_glb_rec *glb_rec = (struct lquota_glb_rec *)rec;
359 /* doesn't change quota enforcement if the quota entry is still
360 * using default quota. */
361 if (LQUOTA_FLAG(glb_rec->qbr_time) & LQUOTA_FLAG_DEFAULT &&
362 glb_rec->qbr_hardlimit == 0 && glb_rec->qbr_softlimit == 0)
365 LQUOTA_DEBUG(lqe, "the ID has been set quota, so clear the"
366 " default quota flag");
367 lqe->lqe_is_default = false;
369 /* change enforcement status based on new hard/soft limit */
370 if (lqe->lqe_id.qid_uid != 0 && (glb_rec->qbr_hardlimit != 0 ||
371 glb_rec->qbr_softlimit != 0))
372 lqe->lqe_enforced = true;
374 lqe->lqe_enforced = false;
376 LQUOTA_DEBUG(lqe, "updating global index hardlimit: %llu, "
377 "softlimit: %llu", glb_rec->qbr_hardlimit,
378 glb_rec->qbr_softlimit);
380 struct lquota_slv_rec *slv_rec = (struct lquota_slv_rec *)rec;
382 lqe->lqe_granted = slv_rec->qsr_granted;
384 LQUOTA_DEBUG(lqe, "updating slave index, granted:%llu",
385 slv_rec->qsr_granted);