Whamcloud - gitweb
b=16890 CERROR cleanups
[fs/lustre-release.git] / lustre / quota / lproc_quota.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright  2008 Sun Microsystems, Inc. All rights reserved
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  */
36
37 #define DEBUG_SUBSYSTEM S_LQUOTA
38
39 #include <linux/version.h>
40 #include <lprocfs_status.h>
41 #include <obd.h>
42 #include <linux/seq_file.h>
43 #include <lustre_fsfilt.h>
44
45 #include "quota_internal.h"
46
47 #ifdef HAVE_QUOTA_SUPPORT
48
49 #ifdef LPROCFS
50 int lprocfs_quota_rd_bunit(char *page, char **start, off_t off, int count,
51                            int *eof, void *data)
52 {
53         struct obd_device *obd = (struct obd_device *)data;
54         LASSERT(obd != NULL);
55
56         return snprintf(page, count, "%lu\n",
57                         obd->u.obt.obt_qctxt.lqc_bunit_sz);
58 }
59 EXPORT_SYMBOL(lprocfs_quota_rd_bunit);
60
61 int lprocfs_quota_wr_bunit(struct file *file, const char *buffer,
62                            unsigned long count, void *data)
63 {
64         struct obd_device *obd = (struct obd_device *)data;
65         int val, rc;
66         LASSERT(obd != NULL);
67
68         rc = lprocfs_write_helper(buffer, count, &val);
69         if (rc)
70                 return rc;
71
72         if (val % QUOTABLOCK_SIZE ||
73             val <= obd->u.obt.obt_qctxt.lqc_btune_sz)
74                 return -EINVAL;
75
76         obd->u.obt.obt_qctxt.lqc_bunit_sz = val;
77         return count;
78 }
79 EXPORT_SYMBOL(lprocfs_quota_wr_bunit);
80
81 int lprocfs_quota_rd_btune(char *page, char **start, off_t off, int count,
82                            int *eof, void *data)
83 {
84         struct obd_device *obd = (struct obd_device *)data;
85         LASSERT(obd != NULL);
86
87         return snprintf(page, count, "%lu\n",
88                         obd->u.obt.obt_qctxt.lqc_btune_sz);
89 }
90 EXPORT_SYMBOL(lprocfs_quota_rd_btune);
91
92 int lprocfs_quota_wr_btune(struct file *file, const char *buffer,
93                            unsigned long count, void *data)
94 {
95         struct obd_device *obd = (struct obd_device *)data;
96         int val, rc;
97         LASSERT(obd != NULL);
98
99         rc = lprocfs_write_helper(buffer, count, &val);
100         if (rc)
101                 return rc;
102
103         if (val <= QUOTABLOCK_SIZE * MIN_QLIMIT || val % QUOTABLOCK_SIZE ||
104             val >= obd->u.obt.obt_qctxt.lqc_bunit_sz)
105                 return -EINVAL;
106
107         obd->u.obt.obt_qctxt.lqc_btune_sz = val;
108         return count;
109 }
110 EXPORT_SYMBOL(lprocfs_quota_wr_btune);
111
112 int lprocfs_quota_rd_iunit(char *page, char **start, off_t off, int count,
113                            int *eof, void *data)
114 {
115         struct obd_device *obd = (struct obd_device *)data;
116         LASSERT(obd != NULL);
117
118         return snprintf(page, count, "%lu\n",
119                         obd->u.obt.obt_qctxt.lqc_iunit_sz);
120 }
121 EXPORT_SYMBOL(lprocfs_quota_rd_iunit);
122
123 int lprocfs_quota_wr_iunit(struct file *file, const char *buffer,
124                            unsigned long count, void *data)
125 {
126         struct obd_device *obd = (struct obd_device *)data;
127         int val, rc;
128         LASSERT(obd != NULL);
129
130         rc = lprocfs_write_helper(buffer, count, &val);
131         if (rc)
132                 return rc;
133
134         if (val <= obd->u.obt.obt_qctxt.lqc_itune_sz)
135                 return -EINVAL;
136
137         obd->u.obt.obt_qctxt.lqc_iunit_sz = val;
138         return count;
139 }
140 EXPORT_SYMBOL(lprocfs_quota_wr_iunit);
141
142 int lprocfs_quota_rd_itune(char *page, char **start, off_t off, int count,
143                            int *eof, void *data)
144 {
145         struct obd_device *obd = (struct obd_device *)data;
146         LASSERT(obd != NULL);
147
148         return snprintf(page, count, "%lu\n",
149                         obd->u.obt.obt_qctxt.lqc_itune_sz);
150 }
151 EXPORT_SYMBOL(lprocfs_quota_rd_itune);
152
153 int lprocfs_quota_wr_itune(struct file *file, const char *buffer,
154                            unsigned long count, void *data)
155 {
156         struct obd_device *obd = (struct obd_device *)data;
157         int val, rc;
158         LASSERT(obd != NULL);
159
160         rc = lprocfs_write_helper(buffer, count, &val);
161         if (rc)
162                 return rc;
163
164         if (val <= MIN_QLIMIT ||
165             val >= obd->u.obt.obt_qctxt.lqc_iunit_sz)
166                 return -EINVAL;
167
168         obd->u.obt.obt_qctxt.lqc_itune_sz = val;
169         return count;
170 }
171 EXPORT_SYMBOL(lprocfs_quota_wr_itune);
172
173 #define USER_QUOTA      1
174 #define GROUP_QUOTA     2
175
176 #define MAX_STYPE_SIZE  5
177
178 int lprocfs_quota_rd_type(char *page, char **start, off_t off, int count,
179                           int *eof, void *data)
180 {
181         struct obd_device *obd = (struct obd_device *)data;
182         char stype[MAX_STYPE_SIZE + 1] = "";
183         int oq_type;
184         struct obd_device_target *obt;
185
186         LASSERT(obd != NULL);
187
188         obt = &obd->u.obt;
189
190         /* Collect the needed information */
191         oq_type = obd->u.obt.obt_qctxt.lqc_flags;
192
193         /* Transform the collected data into a user-readable string */
194         if (oq_type & LQC_USRQUOTA_FLAG)
195                 strcat(stype, "u");
196         if (oq_type & LQC_GRPQUOTA_FLAG)
197                 strcat(stype, "g");
198
199         strcat(stype, "3");
200
201         return snprintf(page, count, "%s\n", stype);
202 }
203 EXPORT_SYMBOL(lprocfs_quota_rd_type);
204
205 static int auto_quota_on(struct obd_device *obd, int type,
206                          struct super_block *sb, int is_master)
207 {
208         struct obd_quotactl *oqctl;
209         struct lvfs_run_ctxt saved;
210         int rc = 0, rc1 = 0, id;
211         struct obd_device_target *obt = &obd->u.obt;
212         struct lustre_quota_ctxt *qctxt = &obt->obt_qctxt;
213         struct mds_obd *mds = NULL;
214         ENTRY;
215
216         LASSERT(type == USRQUOTA || type == GRPQUOTA || type == UGQUOTA);
217
218         OBD_ALLOC_PTR(oqctl);
219         if (!oqctl)
220                 RETURN(-ENOMEM);
221
222         down(&obt->obt_quotachecking);
223         id = UGQUOTA2LQC(type);
224         /* quota already turned on */
225         if ((obt->obt_qctxt.lqc_flags & id) == id)
226                 GOTO(out, rc);
227
228         if (obt->obt_qctxt.lqc_immutable) {
229                 LCONSOLE_ERROR("Failed to turn Quota on, immutable mode "
230                                "(is SOM enabled?)\n");
231                 GOTO(out, rc = -ECANCELED);
232         }
233
234         oqctl->qc_type = type;
235         oqctl->qc_cmd = Q_QUOTAON;
236         oqctl->qc_id = obt->obt_qfmt;
237
238         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
239
240         if (is_master) {
241                 mds = &obd->u.mds;
242                 down(&mds->mds_qonoff_sem);
243                 /* turn on cluster wide quota */
244                 rc1 = mds_admin_quota_on(obd, oqctl);
245                 if (rc1 && rc1 != -EALREADY) {
246                         CDEBUG_LIMIT(rc1 == -ENOENT ? D_QUOTA : D_ERROR,
247                                      "%s: auto-enable admin quota failed with "
248                                      "rc=%d\n", obd->obd_name, rc1);
249                         GOTO(out_ctxt, rc1);
250                 }
251         }
252
253         /* turn on local quota */
254         rc = fsfilt_quotactl(obd, sb, oqctl);
255         if (!rc) {
256                 obt->obt_qctxt.lqc_flags |= UGQUOTA2LQC(type);
257                 build_lqs(obd);
258         } else if (rc == -EBUSY && quota_is_on(qctxt, oqctl)) {
259                 CWARN("%s: mds local quota[%d] is on already\n",
260                       obd->obd_name, oqctl->qc_type);
261                 rc = -EALREADY;
262         } else {
263                 CDEBUG_LIMIT(rc == -ENOENT ? D_QUOTA : D_ERROR,
264                              "%s: auto-enable local quota failed with rc=%d\n",
265                              obd->obd_name, rc);
266                 if (rc1 == -EALREADY) {
267                         oqctl->qc_cmd = Q_QUOTAOFF;
268                         mds_admin_quota_off(obd, oqctl);
269                 }
270                 if (rc == -ENOENT)
271                         CWARN("%s: quotaon failed because quota files don't "
272                               "exist, please run quotacheck firstly\n",
273                               obd->obd_name);
274
275                 GOTO(out_ctxt, rc);
276         }
277
278         EXIT;
279
280 out_ctxt:
281         if (mds != NULL)
282                 up(&mds->mds_qonoff_sem);
283         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
284
285 out:
286         up(&obt->obt_quotachecking);
287         OBD_FREE_PTR(oqctl);
288         return rc;
289 }
290
291 int lprocfs_quota_wr_type(struct file *file, const char *buffer,
292                           unsigned long count, void *data)
293 {
294         struct obd_device *obd = (struct obd_device *)data;
295         struct obd_device_target *obt;
296         int type = 0, is_mds;
297         unsigned long i;
298         char stype[MAX_STYPE_SIZE + 1] = "";
299
300         LASSERT(obd != NULL);
301
302         obt = &obd->u.obt;
303
304         is_mds = !strcmp(obd->obd_type->typ_name, LUSTRE_MDS_NAME);
305
306         if (count > MAX_STYPE_SIZE)
307                 return -EINVAL;
308
309         if (copy_from_user(stype, buffer, count))
310                 return -EFAULT;
311
312         for (i = 0 ; i < count ; i++) {
313                 switch (stype[i]) {
314                 case 'u' :
315                         type |= USER_QUOTA;
316                         break;
317                 case 'g' :
318                         type |= GROUP_QUOTA;
319                         break;
320                 case '1' :
321                 case '2' :
322                         CWARN("quota_type options 1 and 2 are obsolete, "
323                               "they will be ignored\n");
324                         break;
325                 case '3' : /* the only valid version spec, do nothing */
326                 default  : /* just skip stray symbols like \n */
327                         break;
328                 }
329         }
330
331         if (type != 0) {
332                 int rc = auto_quota_on(obd, type - 1, obt->obt_sb, is_mds);
333
334                 if (rc && rc != -EALREADY && rc != -ENOENT)
335                         return rc;
336         }
337
338         return count;
339 }
340 EXPORT_SYMBOL(lprocfs_quota_wr_type);
341
342 int lprocfs_quota_rd_switch_seconds(char *page, char **start, off_t off,
343                                     int count, int *eof, void *data)
344 {
345         struct obd_device *obd = (struct obd_device *)data;
346         LASSERT(obd != NULL);
347
348         return snprintf(page, count, "%d\n",
349                         obd->u.obt.obt_qctxt.lqc_switch_seconds);
350 }
351 EXPORT_SYMBOL(lprocfs_quota_rd_switch_seconds);
352
353 int lprocfs_quota_wr_switch_seconds(struct file *file, const char *buffer,
354                                     unsigned long count, void *data)
355 {
356         struct obd_device *obd = (struct obd_device *)data;
357         int val, rc;
358         LASSERT(obd != NULL);
359
360         rc = lprocfs_write_helper(buffer, count, &val);
361         if (rc)
362                 return rc;
363
364         if (val <= 10)
365                 return -EINVAL;
366
367         obd->u.obt.obt_qctxt.lqc_switch_seconds = val;
368         return count;
369 }
370 EXPORT_SYMBOL(lprocfs_quota_wr_switch_seconds);
371
372 int lprocfs_quota_rd_sync_blk(char *page, char **start, off_t off,
373                               int count, int *eof, void *data)
374 {
375         struct obd_device *obd = (struct obd_device *)data;
376         LASSERT(obd != NULL);
377
378         return snprintf(page, count, "%d\n",
379                         obd->u.obt.obt_qctxt.lqc_sync_blk);
380 }
381 EXPORT_SYMBOL(lprocfs_quota_rd_sync_blk);
382
383 int lprocfs_quota_wr_sync_blk(struct file *file, const char *buffer,
384                               unsigned long count, void *data)
385 {
386         struct obd_device *obd = (struct obd_device *)data;
387         int val, rc;
388         LASSERT(obd != NULL);
389
390         rc = lprocfs_write_helper(buffer, count, &val);
391         if (rc)
392                 return rc;
393
394         if (val < 0)
395                 return -EINVAL;
396
397         obd->u.obt.obt_qctxt.lqc_sync_blk = val;
398         return count;
399 }
400 EXPORT_SYMBOL(lprocfs_quota_wr_sync_blk);
401
402 int lprocfs_quota_rd_switch_qs(char *page, char **start, off_t off,
403                                int count, int *eof, void *data)
404 {
405         struct obd_device *obd = (struct obd_device *)data;
406         LASSERT(obd != NULL);
407
408         return snprintf(page, count, "changing qunit size is %s\n",
409                         obd->u.obt.obt_qctxt.lqc_switch_qs ?
410                         "enabled" : "disabled");
411 }
412 EXPORT_SYMBOL(lprocfs_quota_rd_switch_qs);
413
414 int lprocfs_quota_wr_switch_qs(struct file *file, const char *buffer,
415                                unsigned long count, void *data)
416 {
417         struct obd_device *obd = (struct obd_device *)data;
418         int val, rc;
419         LASSERT(obd != NULL);
420
421         rc = lprocfs_write_helper(buffer, count, &val);
422         if (rc)
423                 return rc;
424
425         if (val)
426             obd->u.obt.obt_qctxt.lqc_switch_qs = 1;
427         else
428             obd->u.obt.obt_qctxt.lqc_switch_qs = 0;
429
430         return count;
431 }
432 EXPORT_SYMBOL(lprocfs_quota_wr_switch_qs);
433
434 int lprocfs_quota_rd_boundary_factor(char *page, char **start, off_t off,
435                                      int count, int *eof, void *data)
436 {
437         struct obd_device *obd = (struct obd_device *)data;
438         LASSERT(obd != NULL);
439
440
441         return snprintf(page, count, "%lu\n",
442                         obd->u.obt.obt_qctxt.lqc_cqs_boundary_factor);
443 }
444 EXPORT_SYMBOL(lprocfs_quota_rd_boundary_factor);
445
446 int lprocfs_quota_wr_boundary_factor(struct file *file, const char *buffer,
447                                      unsigned long count, void *data)
448 {
449         struct obd_device *obd = (struct obd_device *)data;
450         int val, rc;
451         LASSERT(obd != NULL);
452
453         rc = lprocfs_write_helper(buffer, count, &val);
454         if (rc)
455                 return rc;
456
457         if (val < 2)
458                 return -EINVAL;
459
460         obd->u.obt.obt_qctxt.lqc_cqs_boundary_factor = val;
461         return count;
462 }
463 EXPORT_SYMBOL(lprocfs_quota_wr_boundary_factor);
464
465 int lprocfs_quota_rd_least_bunit(char *page, char **start, off_t off,
466                                  int count, int *eof, void *data)
467 {
468         struct obd_device *obd = (struct obd_device *)data;
469         LASSERT(obd != NULL);
470
471
472         return snprintf(page, count, "%lu\n",
473                         obd->u.obt.obt_qctxt.lqc_cqs_least_bunit);
474 }
475 EXPORT_SYMBOL(lprocfs_quota_rd_least_bunit);
476
477 int lprocfs_quota_wr_least_bunit(struct file *file, const char *buffer,
478                                  unsigned long count, void *data)
479 {
480         struct obd_device *obd = (struct obd_device *)data;
481         int val, rc;
482         LASSERT(obd != NULL);
483
484         rc = lprocfs_write_helper(buffer, count, &val);
485         if (rc)
486                 return rc;
487
488         if (val < PTLRPC_MAX_BRW_SIZE ||
489             val >= obd->u.obt.obt_qctxt.lqc_bunit_sz)
490                 return -EINVAL;
491
492         obd->u.obt.obt_qctxt.lqc_cqs_least_bunit = val;
493         return count;
494 }
495 EXPORT_SYMBOL(lprocfs_quota_wr_least_bunit);
496
497 int lprocfs_quota_rd_least_iunit(char *page, char **start, off_t off,
498                                  int count, int *eof, void *data)
499 {
500         struct obd_device *obd = (struct obd_device *)data;
501         LASSERT(obd != NULL);
502
503
504         return snprintf(page, count, "%lu\n",
505                         obd->u.obt.obt_qctxt.lqc_cqs_least_iunit);
506 }
507 EXPORT_SYMBOL(lprocfs_quota_rd_least_iunit);
508
509 int lprocfs_quota_wr_least_iunit(struct file *file, const char *buffer,
510                                  unsigned long count, void *data)
511 {
512         struct obd_device *obd = (struct obd_device *)data;
513         int val, rc;
514         LASSERT(obd != NULL);
515
516         rc = lprocfs_write_helper(buffer, count, &val);
517         if (rc)
518                 return rc;
519
520         if (val < 1 || val >= obd->u.obt.obt_qctxt.lqc_iunit_sz)
521                 return -EINVAL;
522
523         obd->u.obt.obt_qctxt.lqc_cqs_least_iunit = val;
524         return count;
525 }
526 EXPORT_SYMBOL(lprocfs_quota_wr_least_iunit);
527
528 int lprocfs_quota_rd_qs_factor(char *page, char **start, off_t off,
529                                int count, int *eof, void *data)
530 {
531         struct obd_device *obd = (struct obd_device *)data;
532         LASSERT(obd != NULL);
533
534
535         return snprintf(page, count, "%lu\n",
536                         obd->u.obt.obt_qctxt.lqc_cqs_qs_factor);
537 }
538 EXPORT_SYMBOL(lprocfs_quota_rd_qs_factor);
539
540 int lprocfs_quota_wr_qs_factor(struct file *file, const char *buffer,
541                                unsigned long count, void *data)
542 {
543         struct obd_device *obd = (struct obd_device *)data;
544         int val, rc;
545         LASSERT(obd != NULL);
546
547         rc = lprocfs_write_helper(buffer, count, &val);
548         if (rc)
549                 return rc;
550
551         if (val < 2)
552                 return -EINVAL;
553
554         obd->u.obt.obt_qctxt.lqc_cqs_qs_factor = val;
555         return count;
556 }
557 EXPORT_SYMBOL(lprocfs_quota_wr_qs_factor);
558
559 struct lprocfs_vars lprocfs_quota_common_vars[] = {
560         { "quota_bunit_sz", lprocfs_quota_rd_bunit,
561                             lprocfs_quota_wr_bunit, 0},
562         { "quota_btune_sz", lprocfs_quota_rd_btune,
563                             lprocfs_quota_wr_btune, 0},
564         { "quota_iunit_sz", lprocfs_quota_rd_iunit,
565                             lprocfs_quota_wr_iunit, 0},
566         { "quota_itune_sz", lprocfs_quota_rd_itune,
567                             lprocfs_quota_wr_itune, 0},
568         { "quota_type",     lprocfs_quota_rd_type,
569                             lprocfs_quota_wr_type, 0},
570         { "quota_switch_seconds",  lprocfs_quota_rd_switch_seconds,
571                                    lprocfs_quota_wr_switch_seconds, 0 },
572         { "quota_sync_blk", lprocfs_quota_rd_sync_blk,
573                             lprocfs_quota_wr_sync_blk, 0},
574         { NULL }
575 };
576
577 struct lprocfs_vars lprocfs_quota_master_vars[] = {
578         { "quota_switch_qs", lprocfs_quota_rd_switch_qs,
579                              lprocfs_quota_wr_switch_qs, 0 },
580         { "quota_boundary_factor", lprocfs_quota_rd_boundary_factor,
581                                    lprocfs_quota_wr_boundary_factor, 0 },
582         { "quota_least_bunit", lprocfs_quota_rd_least_bunit,
583                                lprocfs_quota_wr_least_bunit, 0 },
584         { "quota_least_iunit", lprocfs_quota_rd_least_iunit,
585                                lprocfs_quota_wr_least_iunit, 0 },
586         { "quota_qs_factor",   lprocfs_quota_rd_qs_factor,
587                                lprocfs_quota_wr_qs_factor, 0 },
588         { NULL }
589 };
590
591 int lquota_proc_setup(struct obd_device *obd, int is_master)
592 {
593         struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt;
594         int rc = 0;
595         ENTRY;
596
597         LASSERT(lquota_type_proc_dir && obd);
598         qctxt->lqc_proc_dir = lprocfs_register(obd->obd_name,
599                                                lquota_type_proc_dir,
600                                                lprocfs_quota_common_vars, obd);
601         if (IS_ERR(qctxt->lqc_proc_dir)) {
602                 rc = PTR_ERR(qctxt->lqc_proc_dir);
603                 CERROR("%s: error %d setting up lprocfs\n",
604                        obd->obd_name, rc);
605                 qctxt->lqc_proc_dir = NULL;
606                 GOTO(out, rc);
607         }
608
609         if (is_master) {
610                 rc = lprocfs_add_vars(qctxt->lqc_proc_dir,
611                                       lprocfs_quota_master_vars, obd);
612                 if (rc) {
613                         CERROR("%s: error %d setting up lprocfs for "
614                                "quota master\n", obd->obd_name, rc);
615                         GOTO(out_free_proc, rc);
616                 }
617         }
618
619         qctxt->lqc_stats = lprocfs_alloc_stats(LQUOTA_LAST_STAT -
620                                                LQUOTA_FIRST_STAT, 0);
621         if (!qctxt->lqc_stats)
622                 GOTO(out_free_proc, rc = -ENOMEM);
623
624         lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_SYNC_ACQ,
625                              LPROCFS_CNTR_AVGMINMAX, "sync_acq_req", "us");
626         lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_SYNC_REL,
627                              LPROCFS_CNTR_AVGMINMAX, "sync_rel_req", "us");
628         lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_ASYNC_ACQ,
629                              LPROCFS_CNTR_AVGMINMAX, "async_acq_req", "us");
630         lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_ASYNC_REL,
631                              LPROCFS_CNTR_AVGMINMAX, "async_rel_req", "us");
632
633         lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_FOR_CHK_BLK,
634                              LPROCFS_CNTR_AVGMINMAX,
635                              "wait_for_blk_quota(lquota_chkquota)", "us");
636         lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_FOR_CHK_INO,
637                              LPROCFS_CNTR_AVGMINMAX,
638                              "wait_for_ino_quota(lquota_chkquota)", "us");
639         lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_FOR_COMMIT_BLK,
640                              LPROCFS_CNTR_AVGMINMAX,
641                              "wait_for_blk_quota(lquota_pending_commit)",
642                              "us");
643         lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_FOR_COMMIT_INO,
644                              LPROCFS_CNTR_AVGMINMAX,
645                              "wait_for_ino_quota(lquota_pending_commit)",
646                              "us");
647
648         lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_PENDING_BLK_QUOTA,
649                              LPROCFS_CNTR_AVGMINMAX,
650                              "wait_for_pending_blk_quota_req"
651                              "(qctxt_wait_pending_dqacq)", "us");
652         lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_PENDING_INO_QUOTA,
653                              LPROCFS_CNTR_AVGMINMAX,
654                              "wait_for_pending_ino_quota_req"
655                              "(qctxt_wait_pending_dqacq)", "us");
656         lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_NOWAIT_PENDING_BLK_QUOTA,
657                              LPROCFS_CNTR_AVGMINMAX,
658                              "nowait_for_pending_blk_quota_req"
659                              "(qctxt_wait_pending_dqacq)", "us");
660         lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_NOWAIT_PENDING_INO_QUOTA,
661                              LPROCFS_CNTR_AVGMINMAX,
662                              "nowait_for_pending_ino_quota_req"
663                              "(qctxt_wait_pending_dqacq)", "us");
664
665         lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_QUOTA_CTL,
666                              LPROCFS_CNTR_AVGMINMAX, "quota_ctl", "us");
667         lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_ADJUST_QUNIT,
668                              LPROCFS_CNTR_AVGMINMAX, "adjust_qunit", "us");
669
670         lprocfs_register_stats(qctxt->lqc_proc_dir, "stats", qctxt->lqc_stats);
671
672         RETURN(rc);
673
674 out_free_proc:
675         lprocfs_remove(&qctxt->lqc_proc_dir);
676 out:
677         RETURN(rc);
678 }
679
680 int lquota_proc_cleanup(struct lustre_quota_ctxt *qctxt)
681 {
682         if (!qctxt || !qctxt->lqc_proc_dir)
683                 return -EINVAL;
684
685         if (qctxt->lqc_stats != NULL)
686                  lprocfs_free_stats(&qctxt->lqc_stats);
687
688         lprocfs_remove(&qctxt->lqc_proc_dir);
689         return 0;
690 }
691
692 #endif  /* LPROCFS */
693 #endif