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 Whamcloud, Inc.
25 * Use is subject to license terms.
27 * Author: Johann Lombardi <johann@whamcloud.com>
28 * Author: Niu Yawei <niu@whamcloud.com>
32 * Quota Slave Driver (QSD) management.
36 # define EXPORT_SYMTAB
39 #define DEBUG_SUBSYSTEM S_LQUOTA
41 #include "qsd_internal.h"
43 /* some procfs helpers */
44 static int lprocfs_qsd_rd_state(char *page, char **start, off_t off,
45 int count, int *eof, void *data)
47 struct qsd_instance *qsd = (struct qsd_instance *)data;
51 return snprintf(page, count,
53 "quota enabled: none\n",
57 static struct lprocfs_vars lprocfs_quota_qsd_vars[] = {
58 { "info", lprocfs_qsd_rd_state, 0, 0},
63 * Release qsd_qtype_info structure which contains data associated with a
64 * given quota type. This releases the accounting objects.
65 * It's called on OSD cleanup when the qsd instance is released.
67 * \param env - is the environment passed by the caller
68 * \param qsd - is the qsd instance managing the qsd_qtype_info structure
70 * \param qtype - is the quota type to be shutdown
72 static void qsd_qtype_fini(const struct lu_env *env, struct qsd_instance *qsd,
75 struct qsd_qtype_info *qqi;
78 if (qsd->qsd_type_array[qtype] == NULL)
80 qqi = qsd->qsd_type_array[qtype];
81 qsd->qsd_type_array[qtype] = NULL;
83 /* release accounting object */
84 if (qqi->qqi_acct_obj != NULL && !IS_ERR(qqi->qqi_acct_obj)) {
85 lu_object_put(env, &qqi->qqi_acct_obj->do_lu);
86 qqi->qqi_acct_obj = NULL;
94 * Allocate and initialize a qsd_qtype_info structure for quota type \qtype.
95 * This opens the accounting object and initializes the proc file.
96 * It's called on OSD start when the qsd instance is created.
98 * \param env - the environment passed by the caller
99 * \param qsd - is the qsd instance which will be in charge of the new
100 * qsd_qtype_info instance.
101 * \param qtype - is quota type to set up
103 * \retval - 0 on success and qsd->qsd_type_array[qtype] is allocated,
104 * appropriate error on failure
106 static int qsd_qtype_init(const struct lu_env *env, struct qsd_instance *qsd,
109 struct qsd_qtype_info *qqi;
113 LASSERT(qsd->qsd_type_array[qtype] == NULL);
115 /* allocate structure for this quota type */
119 qsd->qsd_type_array[qtype] = qqi;
121 /* set backpointer and other parameters */
123 qqi->qqi_qtype = qtype;
125 /* open accounting object */
126 LASSERT(qqi->qqi_acct_obj == NULL);
127 qqi->qqi_acct_obj = acct_obj_lookup(env, qsd->qsd_dev,
128 qtype == USRQUOTA ? ACCT_USER_OID
130 /* don't print any error message on failure in order not to confuse
131 * non-OFD user (e.g. 2.3 MDT stack) */
132 if (IS_ERR(qqi->qqi_acct_obj))
133 qqi->qqi_acct_obj = NULL;
135 /* register proc entry for accounting object */
136 rc = lprocfs_seq_create(qsd->qsd_proc,
137 qtype == USRQUOTA ? "acct_user" : "acct_group",
138 0444, &lprocfs_quota_seq_fops,
141 CWARN("%s: can't add procfs entry for accounting file %d\n",
142 qsd->qsd_svname, rc);
149 qsd_qtype_fini(env, qsd, qtype);
154 * Release a qsd_instance. Companion of qsd_init(). This releases all data
155 * structures associated with the quota slave.
156 * This function should be called when the OSD is shutting down.
158 * \param env - is the environment passed by the caller
159 * \param qsd - is the qsd instance to shutdown
161 void qsd_fini(const struct lu_env *env, struct qsd_instance *qsd)
166 /* remove qsd proc entry */
167 if (qsd->qsd_proc != NULL && !IS_ERR(qsd->qsd_proc)) {
168 lprocfs_remove(&qsd->qsd_proc);
169 qsd->qsd_proc = NULL;
172 /* free per-quota type data */
173 for (qtype = USRQUOTA; qtype < MAXQUOTAS; qtype++)
174 qsd_qtype_fini(env, qsd, qtype);
176 /* release reference on dt_device */
177 if (qsd->qsd_dev != NULL) {
178 lu_ref_del(&qsd->qsd_dev->dd_lu_dev.ld_reference, "qsd", qsd);
179 lu_device_put(&qsd->qsd_dev->dd_lu_dev);
186 EXPORT_SYMBOL(qsd_fini);
189 * Create a new qsd_instance to be associated with backend osd device
190 * identified by \dev. For now, this function just create procfs files which
191 * dumps the accounting information
193 * \param env - the environment passed by the caller
194 * \param svname - is the service name of the OSD device creating this instance
195 * \param dev - is the dt_device where to store quota index files
196 * \param osd_proc - is the procfs parent directory where to create procfs file
197 * related to this new qsd instance
199 * \retval - pointer to new qsd_instance associated with dev \dev on success,
200 * appropriate error on failure
202 struct qsd_instance *qsd_init(const struct lu_env *env, char *svname,
203 struct dt_device *dev,
204 cfs_proc_dir_entry_t *osd_proc)
206 struct qsd_instance *qsd;
210 /* allocate qsd instance */
213 RETURN(ERR_PTR(-ENOMEM));
215 /* copy service name */
216 strncpy(qsd->qsd_svname, svname, MAX_OBD_NAME);
218 /* grab reference on osd device */
219 lu_device_get(&dev->dd_lu_dev);
220 lu_ref_add(&dev->dd_lu_dev.ld_reference, "qsd", qsd);
223 /* register procfs directory */
224 qsd->qsd_proc = lprocfs_register(QSD_DIR, osd_proc,
225 lprocfs_quota_qsd_vars, qsd);
226 if (IS_ERR(qsd->qsd_proc)) {
227 rc = PTR_ERR(qsd->qsd_proc);
228 CERROR("%s: fail to create quota slave proc entry (%d)\n",
233 /* initialize per-quota type data */
234 for (qtype = USRQUOTA; qtype < MAXQUOTAS; qtype++) {
235 rc = qsd_qtype_init(env, qsd, qtype);
246 EXPORT_SYMBOL(qsd_init);