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