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