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 Intel, Inc.
25 * Use is subject to license terms.
27 * Author: Johann Lombardi <johann.lombardi@intel.com>
28 * Author: Niu Yawei <yawei.niu@intel.com>
32 # define EXPORT_SYMTAB
35 #define DEBUG_SUBSYSTEM S_LQUOTA
37 #include <obd_class.h>
38 #include <lustre_param.h>
40 #include "qsd_internal.h"
42 static CFS_LIST_HEAD(qfs_list);
43 /* protect the qfs_list */
44 static DEFINE_SPINLOCK(qfs_list_lock);
47 * Put reference of qsd_fsinfo.
49 * \param qfs - the qsd_fsinfo to be put
51 void qsd_put_fsinfo(struct qsd_fsinfo *qfs)
56 cfs_spin_lock(&qfs_list_lock);
57 LASSERT(qfs->qfs_ref > 0);
59 if (qfs->qfs_ref == 0) {
60 LASSERT(cfs_list_empty(&qfs->qfs_qsd_list));
61 cfs_list_del(&qfs->qfs_link);
64 cfs_spin_unlock(&qfs_list_lock);
69 * Find or create a qsd_fsinfo
71 * \param name - filesystem name
72 * \param create - when @create is non-zero, create new one if fail to
73 * find existing qfs by @name
75 * \retval qsd_fsinfo - success
76 * \retval NULL - failure
78 struct qsd_fsinfo *qsd_get_fsinfo(char *name, bool create)
80 struct qsd_fsinfo *qfs, *new = NULL;
83 if (name == NULL || strlen(name) >= MTI_NAME_MAXLEN)
87 /* pre-allocate a qsd_fsinfo in case there isn't one already.
88 * we can afford the extra cost since qsd_get_fsinfo() isn't
89 * called very often with create = true */
95 cfs_sema_init(&new->qfs_sem, 1);
96 CFS_INIT_LIST_HEAD(&new->qfs_qsd_list);
97 strcpy(new->qfs_name, name);
101 /* search in the fsinfo list */
102 cfs_spin_lock(&qfs_list_lock);
103 cfs_list_for_each_entry(qfs, &qfs_list, qfs_link) {
104 if (!strcmp(qfs->qfs_name, name)) {
110 qfs = NULL; /* not found */
113 /* not found, but we were asked to create a new one */
114 cfs_list_add_tail(&new->qfs_link, &qfs_list);
119 cfs_spin_unlock(&qfs_list_lock);
127 * Quota configuration handlers in charge of processing all per-filesystem quota
128 * parameters set via conf_param.
130 * \param lcfg - quota configuration log to be processed
132 int qsd_process_config(struct lustre_cfg *lcfg)
134 struct qsd_fsinfo *qfs;
135 char *fsname = lustre_cfg_string(lcfg, 0);
136 char *cfgstr = lustre_cfg_string(lcfg, 1);
137 char *keystr, *valstr;
138 int rc, pool, enabled = 0;
142 CDEBUG(D_QUOTA, "processing quota parameter: fs:%s cfgstr:%s\n", fsname,
145 if (class_match_param(cfgstr, PARAM_QUOTA, &keystr) != 0)
148 if (!class_match_param(keystr, QUOTA_METAPOOL_NAME, &valstr))
149 pool = LQUOTA_RES_MD;
150 else if (!class_match_param(keystr, QUOTA_DATAPOOL_NAME, &valstr))
151 pool = LQUOTA_RES_DT;
155 qfs = qsd_get_fsinfo(fsname, 0);
157 CERROR("failed to find quota filesystem information for %s\n",
162 if (strchr(valstr, 'u'))
163 enabled |= 1 << USRQUOTA;
164 if (strchr(valstr, 'g'))
165 enabled |= 1 << GRPQUOTA;
167 cfs_down(&qfs->qfs_sem);
168 if (qfs->qfs_enabled[pool - LQUOTA_FIRST_RES] == enabled)
169 /* no change required */
172 if ((qfs->qfs_enabled[pool - LQUOTA_FIRST_RES] & enabled) != enabled)
175 qfs->qfs_enabled[pool - LQUOTA_FIRST_RES] = enabled;
177 /* trigger reintegration for all qsd */
179 struct qsd_instance *qsd;
180 struct qsd_qtype_info *qqi;
182 cfs_list_for_each_entry(qsd, &qfs->qfs_qsd_list, qsd_link) {
186 /* start reintegration only if qsd_prepare() was
187 * successfully called */
188 cfs_read_lock(&qsd->qsd_lock);
189 if (!qsd->qsd_prepared)
191 cfs_read_unlock(&qsd->qsd_lock);
195 for (type = USRQUOTA; type < MAXQUOTAS; type++) {
196 qqi = qsd->qsd_type_array[type];
197 qsd_start_reint_thread(qqi);
202 cfs_up(&qfs->qfs_sem);