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