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, 2014, 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 <obd_class.h>
34 #include <uapi/linux/lustre/lustre_param.h>
36 #include "qsd_internal.h"
38 static LIST_HEAD(qfs_list);
39 /* protect the qfs_list */
40 static DEFINE_SPINLOCK(qfs_list_lock);
43 * Put reference of qsd_fsinfo.
45 * \param qfs - the qsd_fsinfo to be put
47 void qsd_put_fsinfo(struct qsd_fsinfo *qfs)
52 spin_lock(&qfs_list_lock);
53 LASSERT(qfs->qfs_ref > 0);
55 if (qfs->qfs_ref == 0) {
56 LASSERT(list_empty(&qfs->qfs_qsd_list));
57 list_del(&qfs->qfs_link);
60 spin_unlock(&qfs_list_lock);
65 * Find or create a qsd_fsinfo
67 * \param name - filesystem name
68 * \param create - when @create is non-zero, create new one if fail to
69 * find existing qfs by @name
71 * \retval qsd_fsinfo - success
72 * \retval NULL - failure
74 struct qsd_fsinfo *qsd_get_fsinfo(char *name, bool create)
76 struct qsd_fsinfo *qfs, *new = NULL;
79 if (name == NULL || strlen(name) >= MTI_NAME_MAXLEN)
83 /* pre-allocate a qsd_fsinfo in case there isn't one already.
84 * we can afford the extra cost since qsd_get_fsinfo() isn't
85 * called very often with create = true */
91 mutex_init(&new->qfs_mutex);
92 INIT_LIST_HEAD(&new->qfs_qsd_list);
93 strcpy(new->qfs_name, name);
97 /* search in the fsinfo list */
98 spin_lock(&qfs_list_lock);
99 list_for_each_entry(qfs, &qfs_list, qfs_link) {
100 if (!strcmp(qfs->qfs_name, name)) {
106 qfs = NULL; /* not found */
109 /* not found, but we were asked to create a new one */
110 list_add_tail(&new->qfs_link, &qfs_list);
115 spin_unlock(&qfs_list_lock);
122 int qsd_config(char *valstr, char *fsname, int pool)
124 struct qsd_fsinfo *qfs;
125 int rc, enabled = 0, old_enabled = 0;
129 qfs = qsd_get_fsinfo(fsname, 0);
131 CERROR("failed to find quota filesystem information for %s\n",
136 if (strchr(valstr, 'u'))
137 enabled |= BIT(USRQUOTA);
138 if (strchr(valstr, 'g'))
139 enabled |= BIT(GRPQUOTA);
140 if (strchr(valstr, 'p'))
141 enabled |= BIT(PRJQUOTA);
143 mutex_lock(&qfs->qfs_mutex);
144 if (qfs->qfs_enabled[pool - LQUOTA_FIRST_RES] == enabled)
145 /* no change required */
148 if ((qfs->qfs_enabled[pool - LQUOTA_FIRST_RES] & enabled) != enabled)
151 old_enabled = qfs->qfs_enabled[pool - LQUOTA_FIRST_RES];
152 qfs->qfs_enabled[pool - LQUOTA_FIRST_RES] = enabled;
154 /* trigger reintegration for all qsd */
156 struct qsd_instance *qsd;
157 struct qsd_qtype_info *qqi;
159 list_for_each_entry(qsd, &qfs->qfs_qsd_list, qsd_link) {
163 /* start reintegration only if qsd_prepare() was
164 * successfully called */
165 read_lock(&qsd->qsd_lock);
166 if (!qsd->qsd_prepared)
168 read_unlock(&qsd->qsd_lock);
172 for (type = USRQUOTA; type < LL_MAXQUOTAS; type++) {
173 qqi = qsd->qsd_type_array[type];
174 /* only trigger reintegration if this
175 * type of quota is not enabled before */
176 if ((old_enabled & BIT(type)) ||
177 !(enabled & BIT(type)))
180 if (qqi->qqi_acct_failed) {
181 LCONSOLE_ERROR("%s: can't enable quota "
182 "enforcement since space "
183 "accounting isn't functional. "
184 "Please run tunefs.lustre "
185 "--quota on an unmounted "
186 "filesystem if not done already"
187 "\n", qsd->qsd_svname);
190 qsd_start_reint_thread(qqi);
195 mutex_unlock(&qfs->qfs_mutex);
201 * Quota configuration handlers in charge of processing all per-filesystem quota
202 * parameters set via conf_param.
204 * \param lcfg - quota configuration log to be processed
206 int qsd_process_config(struct lustre_cfg *lcfg)
208 char *fsname = lustre_cfg_string(lcfg, 0);
209 char *cfgstr = lustre_cfg_string(lcfg, 1);
210 char *keystr, *valstr;
214 CDEBUG(D_QUOTA, "processing quota parameter: fs:%s cfgstr:%s\n", fsname,
217 if (class_match_param(cfgstr, PARAM_QUOTA, &keystr) != 0)
220 if (!class_match_param(keystr, QUOTA_METAPOOL_NAME, &valstr))
221 pool = LQUOTA_RES_MD;
222 else if (!class_match_param(keystr, QUOTA_DATAPOOL_NAME, &valstr))
223 pool = LQUOTA_RES_DT;
227 return qsd_config(valstr, fsname, pool);