Whamcloud - gitweb
a64d7a945ca73bdf6367019037acb9141d4978db
[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(rc1 == -ENOENT ? D_QUOTA : D_ERROR,
247                                "auto-enable admin quota failed. rc=%d\n", rc1);
248                         GOTO(out_ctxt, rc1);
249                 }
250         }
251
252         /* turn on local quota */
253         rc = fsfilt_quotactl(obd, sb, oqctl);
254         if (!rc) {
255                 obt->obt_qctxt.lqc_flags |= UGQUOTA2LQC(type);
256                 build_lqs(obd);
257         } else if (rc == -EBUSY && quota_is_on(qctxt, oqctl)) {
258                 CWARN("%s: mds local quota[%d] is on already\n",
259                       obd->obd_name, oqctl->qc_type);
260                 rc = -EALREADY;
261         } else {
262                 CDEBUG(rc == -ENOENT ? D_QUOTA : D_ERROR,
263                        "auto-enable local quota failed. rc=%d\n", rc);
264                 if (rc1 == -EALREADY) {
265                         oqctl->qc_cmd = Q_QUOTAOFF;
266                         mds_admin_quota_off(obd, oqctl);
267                 }
268                 if (rc == -ENOENT)
269                         CWARN("%s: quotaon failed because quota files don't "
270                               "exist, please run quotacheck firstly\n",
271                               obd->obd_name);
272
273                 GOTO(out_ctxt, rc);
274         }
275
276         EXIT;
277
278 out_ctxt:
279         if (mds != NULL)
280                 up(&mds->mds_qonoff_sem);
281         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
282
283 out:
284         up(&obt->obt_quotachecking);
285         OBD_FREE_PTR(oqctl);
286         return rc;
287 }
288
289 int lprocfs_quota_wr_type(struct file *file, const char *buffer,
290                           unsigned long count, void *data)
291 {
292         struct obd_device *obd = (struct obd_device *)data;
293         struct obd_device_target *obt;
294         int type = 0, is_mds;
295         unsigned long i;
296         char stype[MAX_STYPE_SIZE + 1] = "";
297
298         LASSERT(obd != NULL);
299
300         obt = &obd->u.obt;
301
302         is_mds = !strcmp(obd->obd_type->typ_name, LUSTRE_MDS_NAME);
303
304         if (count > MAX_STYPE_SIZE)
305                 return -EINVAL;
306
307         if (copy_from_user(stype, buffer, count))
308                 return -EFAULT;
309
310         for (i = 0 ; i < count ; i++) {
311                 switch (stype[i]) {
312                 case 'u' :
313                         type |= USER_QUOTA;
314                         break;
315                 case 'g' :
316                         type |= GROUP_QUOTA;
317                         break;
318                 case '1' :
319                 case '2' :
320                         CWARN("quota_type options 1 and 2 are obsolete, "
321                               "they will be ignored\n");
322                         break;
323                 case '3' : /* the only valid version spec, do nothing */
324                 default  : /* just skip stray symbols like \n */
325                         break;
326                 }
327         }
328
329         if (type != 0) {
330                 int rc = auto_quota_on(obd, type - 1, obt->obt_sb, is_mds);
331
332                 if (rc && rc != -EALREADY && rc != -ENOENT)
333                         return rc;
334         }
335
336         return count;
337 }
338 EXPORT_SYMBOL(lprocfs_quota_wr_type);
339
340 int lprocfs_quota_rd_switch_seconds(char *page, char **start, off_t off,
341                                     int count, int *eof, void *data)
342 {
343         struct obd_device *obd = (struct obd_device *)data;
344         LASSERT(obd != NULL);
345
346         return snprintf(page, count, "%d\n",
347                         obd->u.obt.obt_qctxt.lqc_switch_seconds);
348 }
349 EXPORT_SYMBOL(lprocfs_quota_rd_switch_seconds);
350
351 int lprocfs_quota_wr_switch_seconds(struct file *file, const char *buffer,
352                                     unsigned long count, void *data)
353 {
354         struct obd_device *obd = (struct obd_device *)data;
355         int val, rc;
356         LASSERT(obd != NULL);
357
358         rc = lprocfs_write_helper(buffer, count, &val);
359         if (rc)
360                 return rc;
361
362         if (val <= 10)
363                 return -EINVAL;
364
365         obd->u.obt.obt_qctxt.lqc_switch_seconds = val;
366         return count;
367 }
368 EXPORT_SYMBOL(lprocfs_quota_wr_switch_seconds);
369
370 int lprocfs_quota_rd_sync_blk(char *page, char **start, off_t off,
371                               int count, int *eof, void *data)
372 {
373         struct obd_device *obd = (struct obd_device *)data;
374         LASSERT(obd != NULL);
375
376         return snprintf(page, count, "%d\n",
377                         obd->u.obt.obt_qctxt.lqc_sync_blk);
378 }
379 EXPORT_SYMBOL(lprocfs_quota_rd_sync_blk);
380
381 int lprocfs_quota_wr_sync_blk(struct file *file, const char *buffer,
382                               unsigned long count, void *data)
383 {
384         struct obd_device *obd = (struct obd_device *)data;
385         int val, rc;
386         LASSERT(obd != NULL);
387
388         rc = lprocfs_write_helper(buffer, count, &val);
389         if (rc)
390                 return rc;
391
392         if (val < 0)
393                 return -EINVAL;
394
395         obd->u.obt.obt_qctxt.lqc_sync_blk = val;
396         return count;
397 }
398 EXPORT_SYMBOL(lprocfs_quota_wr_sync_blk);
399
400 int lprocfs_quota_rd_switch_qs(char *page, char **start, off_t off,
401                                int count, int *eof, void *data)
402 {
403         struct obd_device *obd = (struct obd_device *)data;
404         LASSERT(obd != NULL);
405
406         return snprintf(page, count, "changing qunit size is %s\n",
407                         obd->u.obt.obt_qctxt.lqc_switch_qs ?
408                         "enabled" : "disabled");
409 }
410 EXPORT_SYMBOL(lprocfs_quota_rd_switch_qs);
411
412 int lprocfs_quota_wr_switch_qs(struct file *file, const char *buffer,
413                                unsigned long count, void *data)
414 {
415         struct obd_device *obd = (struct obd_device *)data;
416         int val, rc;
417         LASSERT(obd != NULL);
418
419         rc = lprocfs_write_helper(buffer, count, &val);
420         if (rc)
421                 return rc;
422
423         if (val)
424             obd->u.obt.obt_qctxt.lqc_switch_qs = 1;
425         else
426             obd->u.obt.obt_qctxt.lqc_switch_qs = 0;
427
428         return count;
429 }
430 EXPORT_SYMBOL(lprocfs_quota_wr_switch_qs);
431
432 int lprocfs_quota_rd_boundary_factor(char *page, char **start, off_t off,
433                                      int count, int *eof, void *data)
434 {
435         struct obd_device *obd = (struct obd_device *)data;
436         LASSERT(obd != NULL);
437
438
439         return snprintf(page, count, "%lu\n",
440                         obd->u.obt.obt_qctxt.lqc_cqs_boundary_factor);
441 }
442 EXPORT_SYMBOL(lprocfs_quota_rd_boundary_factor);
443
444 int lprocfs_quota_wr_boundary_factor(struct file *file, const char *buffer,
445                                      unsigned long count, void *data)
446 {
447         struct obd_device *obd = (struct obd_device *)data;
448         int val, rc;
449         LASSERT(obd != NULL);
450
451         rc = lprocfs_write_helper(buffer, count, &val);
452         if (rc)
453                 return rc;
454
455         if (val < 2)
456                 return -EINVAL;
457
458         obd->u.obt.obt_qctxt.lqc_cqs_boundary_factor = val;
459         return count;
460 }
461 EXPORT_SYMBOL(lprocfs_quota_wr_boundary_factor);
462
463 int lprocfs_quota_rd_least_bunit(char *page, char **start, off_t off,
464                                  int count, int *eof, void *data)
465 {
466         struct obd_device *obd = (struct obd_device *)data;
467         LASSERT(obd != NULL);
468
469
470         return snprintf(page, count, "%lu\n",
471                         obd->u.obt.obt_qctxt.lqc_cqs_least_bunit);
472 }
473 EXPORT_SYMBOL(lprocfs_quota_rd_least_bunit);
474
475 int lprocfs_quota_wr_least_bunit(struct file *file, const char *buffer,
476                                  unsigned long count, void *data)
477 {
478         struct obd_device *obd = (struct obd_device *)data;
479         int val, rc;
480         LASSERT(obd != NULL);
481
482         rc = lprocfs_write_helper(buffer, count, &val);
483         if (rc)
484                 return rc;
485
486         if (val < PTLRPC_MAX_BRW_SIZE ||
487             val >= obd->u.obt.obt_qctxt.lqc_bunit_sz)
488                 return -EINVAL;
489
490         obd->u.obt.obt_qctxt.lqc_cqs_least_bunit = val;
491         return count;
492 }
493 EXPORT_SYMBOL(lprocfs_quota_wr_least_bunit);
494
495 int lprocfs_quota_rd_least_iunit(char *page, char **start, off_t off,
496                                  int count, int *eof, void *data)
497 {
498         struct obd_device *obd = (struct obd_device *)data;
499         LASSERT(obd != NULL);
500
501
502         return snprintf(page, count, "%lu\n",
503                         obd->u.obt.obt_qctxt.lqc_cqs_least_iunit);
504 }
505 EXPORT_SYMBOL(lprocfs_quota_rd_least_iunit);
506
507 int lprocfs_quota_wr_least_iunit(struct file *file, const char *buffer,
508                                  unsigned long count, void *data)
509 {
510         struct obd_device *obd = (struct obd_device *)data;
511         int val, rc;
512         LASSERT(obd != NULL);
513
514         rc = lprocfs_write_helper(buffer, count, &val);
515         if (rc)
516                 return rc;
517
518         if (val < 1 || val >= obd->u.obt.obt_qctxt.lqc_iunit_sz)
519                 return -EINVAL;
520
521         obd->u.obt.obt_qctxt.lqc_cqs_least_iunit = val;
522         return count;
523 }
524 EXPORT_SYMBOL(lprocfs_quota_wr_least_iunit);
525
526 int lprocfs_quota_rd_qs_factor(char *page, char **start, off_t off,
527                                int count, int *eof, void *data)
528 {
529         struct obd_device *obd = (struct obd_device *)data;
530         LASSERT(obd != NULL);
531
532
533         return snprintf(page, count, "%lu\n",
534                         obd->u.obt.obt_qctxt.lqc_cqs_qs_factor);
535 }
536 EXPORT_SYMBOL(lprocfs_quota_rd_qs_factor);
537
538 int lprocfs_quota_wr_qs_factor(struct file *file, const char *buffer,
539                                unsigned long count, void *data)
540 {
541         struct obd_device *obd = (struct obd_device *)data;
542         int val, rc;
543         LASSERT(obd != NULL);
544
545         rc = lprocfs_write_helper(buffer, count, &val);
546         if (rc)
547                 return rc;
548
549         if (val < 2)
550                 return -EINVAL;
551
552         obd->u.obt.obt_qctxt.lqc_cqs_qs_factor = val;
553         return count;
554 }
555 EXPORT_SYMBOL(lprocfs_quota_wr_qs_factor);
556
557 struct lprocfs_vars lprocfs_quota_common_vars[] = {
558         { "quota_bunit_sz", lprocfs_quota_rd_bunit,
559                             lprocfs_quota_wr_bunit, 0},
560         { "quota_btune_sz", lprocfs_quota_rd_btune,
561                             lprocfs_quota_wr_btune, 0},
562         { "quota_iunit_sz", lprocfs_quota_rd_iunit,
563                             lprocfs_quota_wr_iunit, 0},
564         { "quota_itune_sz", lprocfs_quota_rd_itune,
565                             lprocfs_quota_wr_itune, 0},
566         { "quota_type",     lprocfs_quota_rd_type,
567                             lprocfs_quota_wr_type, 0},
568         { "quota_switch_seconds",  lprocfs_quota_rd_switch_seconds,
569                                    lprocfs_quota_wr_switch_seconds, 0 },
570         { "quota_sync_blk", lprocfs_quota_rd_sync_blk,
571                             lprocfs_quota_wr_sync_blk, 0},
572         { NULL }
573 };
574
575 struct lprocfs_vars lprocfs_quota_master_vars[] = {
576         { "quota_switch_qs", lprocfs_quota_rd_switch_qs,
577                              lprocfs_quota_wr_switch_qs, 0 },
578         { "quota_boundary_factor", lprocfs_quota_rd_boundary_factor,
579                                    lprocfs_quota_wr_boundary_factor, 0 },
580         { "quota_least_bunit", lprocfs_quota_rd_least_bunit,
581                                lprocfs_quota_wr_least_bunit, 0 },
582         { "quota_least_iunit", lprocfs_quota_rd_least_iunit,
583                                lprocfs_quota_wr_least_iunit, 0 },
584         { "quota_qs_factor",   lprocfs_quota_rd_qs_factor,
585                                lprocfs_quota_wr_qs_factor, 0 },
586         { NULL }
587 };
588
589 int lquota_proc_setup(struct obd_device *obd, int is_master)
590 {
591         struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt;
592         int rc = 0;
593         ENTRY;
594
595         LASSERT(lquota_type_proc_dir && obd);
596         qctxt->lqc_proc_dir = lprocfs_register(obd->obd_name,
597                                                lquota_type_proc_dir,
598                                                lprocfs_quota_common_vars, obd);
599         if (IS_ERR(qctxt->lqc_proc_dir)) {
600                 rc = PTR_ERR(qctxt->lqc_proc_dir);
601                 CERROR("error %d setting up lprocfs for %s\n", rc,
602                        obd->obd_name);
603                 qctxt->lqc_proc_dir = NULL;
604                 GOTO(out, rc);
605         }
606
607         if (is_master) {
608                 rc = lprocfs_add_vars(qctxt->lqc_proc_dir,
609                                       lprocfs_quota_master_vars, obd);
610                 if (rc) {
611                         CERROR("error %d setting up lprocfs for %s"
612                                "(quota master)\n", rc, obd->obd_name);
613                         GOTO(out_free_proc, rc);
614                 }
615         }
616
617         qctxt->lqc_stats = lprocfs_alloc_stats(LQUOTA_LAST_STAT -
618                                                LQUOTA_FIRST_STAT, 0);
619         if (!qctxt->lqc_stats)
620                 GOTO(out_free_proc, rc = -ENOMEM);
621
622         lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_SYNC_ACQ,
623                              LPROCFS_CNTR_AVGMINMAX, "sync_acq_req", "us");
624         lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_SYNC_REL,
625                              LPROCFS_CNTR_AVGMINMAX, "sync_rel_req", "us");
626         lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_ASYNC_ACQ,
627                              LPROCFS_CNTR_AVGMINMAX, "async_acq_req", "us");
628         lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_ASYNC_REL,
629                              LPROCFS_CNTR_AVGMINMAX, "async_rel_req", "us");
630
631         lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_FOR_CHK_BLK,
632                              LPROCFS_CNTR_AVGMINMAX,
633                              "wait_for_blk_quota(lquota_chkquota)", "us");
634         lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_FOR_CHK_INO,
635                              LPROCFS_CNTR_AVGMINMAX,
636                              "wait_for_ino_quota(lquota_chkquota)", "us");
637         lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_FOR_COMMIT_BLK,
638                              LPROCFS_CNTR_AVGMINMAX,
639                              "wait_for_blk_quota(lquota_pending_commit)",
640                              "us");
641         lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_FOR_COMMIT_INO,
642                              LPROCFS_CNTR_AVGMINMAX,
643                              "wait_for_ino_quota(lquota_pending_commit)",
644                              "us");
645
646         lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_PENDING_BLK_QUOTA,
647                              LPROCFS_CNTR_AVGMINMAX,
648                              "wait_for_pending_blk_quota_req"
649                              "(qctxt_wait_pending_dqacq)", "us");
650         lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_PENDING_INO_QUOTA,
651                              LPROCFS_CNTR_AVGMINMAX,
652                              "wait_for_pending_ino_quota_req"
653                              "(qctxt_wait_pending_dqacq)", "us");
654         lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_NOWAIT_PENDING_BLK_QUOTA,
655                              LPROCFS_CNTR_AVGMINMAX,
656                              "nowait_for_pending_blk_quota_req"
657                              "(qctxt_wait_pending_dqacq)", "us");
658         lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_NOWAIT_PENDING_INO_QUOTA,
659                              LPROCFS_CNTR_AVGMINMAX,
660                              "nowait_for_pending_ino_quota_req"
661                              "(qctxt_wait_pending_dqacq)", "us");
662
663         lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_QUOTA_CTL,
664                              LPROCFS_CNTR_AVGMINMAX, "quota_ctl", "us");
665         lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_ADJUST_QUNIT,
666                              LPROCFS_CNTR_AVGMINMAX, "adjust_qunit", "us");
667
668         lprocfs_register_stats(qctxt->lqc_proc_dir, "stats", qctxt->lqc_stats);
669
670         RETURN(rc);
671
672 out_free_proc:
673         lprocfs_remove(&qctxt->lqc_proc_dir);
674 out:
675         RETURN(rc);
676 }
677
678 int lquota_proc_cleanup(struct lustre_quota_ctxt *qctxt)
679 {
680         if (!qctxt || !qctxt->lqc_proc_dir)
681                 return -EINVAL;
682
683         if (qctxt->lqc_stats != NULL)
684                  lprocfs_free_stats(&qctxt->lqc_stats);
685
686         lprocfs_remove(&qctxt->lqc_proc_dir);
687         return 0;
688 }
689
690 #endif  /* LPROCFS */
691 #endif