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