4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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
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
27 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
30 * Copyright (c) 2011, Whamcloud, Inc.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
37 #define DEBUG_SUBSYSTEM S_LQUOTA
39 #include <linux/version.h>
40 #include <lprocfs_status.h>
42 #include <linux/seq_file.h>
43 #include <lustre_fsfilt.h>
45 #include "lquota_internal.h"
46 #include "quota_internal.h"
49 /* structure allocated at seq_open time and release when seq_release is called.
50 * It is passed to seq_start/stop/next/show which can thus use the same lu_env
51 * to be used with the iterator API */
52 struct lquota_procfs {
53 struct dt_object *lqp_obj;
54 struct lu_env lqp_env;
57 /* global shared environment */
58 static void *lprocfs_quota_seq_start(struct seq_file *p, loff_t *pos)
60 struct lquota_procfs *lqp = p->private;
61 const struct dt_it_ops *iops;
69 return SEQ_START_TOKEN;
72 if (lqp->lqp_obj == NULL)
73 /* accounting not enabled. */
76 /* initialize iterator */
77 iops = &lqp->lqp_obj->do_index_ops->dio_it;
78 it = iops->init(&lqp->lqp_env, lqp->lqp_obj, 0, BYPASS_CAPA);
80 CERROR("%s: failed to initialize iterator: rc = %ld\n",
81 lqp->lqp_obj->do_lu.lo_dev->ld_obd->obd_name,
86 /* move on to the first valid record */
87 rc = iops->load(&lqp->lqp_env, it, 0);
88 if (rc < 0) { /* Error */
92 * Iterator didn't find record with exactly the key requested.
94 * It is currently either
96 * - positioned above record with key less than
97 * requested - skip it.
98 * - or not positioned at all (is in IAM_IT_SKEWED
99 * state) - position it on the next item.
101 rc = iops->next(&lqp->lqp_env, it);
106 rc = iops->next(&lqp->lqp_env, it);
107 if (rc != 0) /* Error or reach the end */
113 iops->put(&lqp->lqp_env, it);
114 iops->fini(&lqp->lqp_env, it);
118 static void lprocfs_quota_seq_stop(struct seq_file *p, void *v)
120 struct lquota_procfs *lqp = p->private;
121 const struct dt_it_ops *iops;
124 if (lqp->lqp_obj == NULL || v == NULL || v == SEQ_START_TOKEN)
127 iops = &lqp->lqp_obj->do_index_ops->dio_it;
128 it = (struct dt_it *)v;
129 /* if something wrong happened during ->seq_show, we need to release
130 * the iterator here */
131 iops->put(&lqp->lqp_env, it);
132 iops->fini(&lqp->lqp_env, it);
135 static void *lprocfs_quota_seq_next(struct seq_file *p, void *v, loff_t *pos)
137 struct lquota_procfs *lqp = p->private;
138 const struct dt_it_ops *iops;
145 if (lqp->lqp_obj == NULL)
148 if (v == SEQ_START_TOKEN)
149 return lprocfs_quota_seq_start(p, pos);
151 iops = &lqp->lqp_obj->do_index_ops->dio_it;
152 it = (struct dt_it *)v;
154 rc = iops->next(&lqp->lqp_env, it);
159 CERROR("%s: seq_next failed: rc = %d\n",
160 lqp->lqp_obj->do_lu.lo_dev->ld_obd->obd_name, rc);
162 /* Reach the end or error */
163 iops->put(&lqp->lqp_env, it);
164 iops->fini(&lqp->lqp_env, it);
173 * usage: { inodes: 209, bytes: 26161152 }
175 * usage: { inodes: 1, bytes: 10485760 }
177 static int lprocfs_quota_seq_show(struct seq_file *p, void *v)
179 struct lquota_procfs *lqp = p->private;
180 const struct dt_it_ops *iops;
183 struct lquota_acct_rec rec;
187 if (lqp->lqp_obj == NULL) {
188 seq_printf(p, "not supported\n");
192 if (v == SEQ_START_TOKEN) {
193 const struct lu_fid *fid = lu_object_fid(&lqp->lqp_obj->do_lu);
195 LASSERT(fid_is_acct(fid));
196 if (fid_oid(fid) == ACCT_USER_OID)
197 seq_printf(p, "user_accounting:\n");
199 seq_printf(p, "group_accounting:\n");
203 iops = &lqp->lqp_obj->do_index_ops->dio_it;
204 it = (struct dt_it *)v;
206 key = iops->key(&lqp->lqp_env, it);
208 CERROR("%s: failed to get key: rc = %ld\n",
209 lqp->lqp_obj->do_lu.lo_dev->ld_obd->obd_name,
214 rc = iops->rec(&lqp->lqp_env, it, (struct dt_rec *)&rec, 0);
216 CERROR("%s: failed to get rec: rc = %d\n",
217 lqp->lqp_obj->do_lu.lo_dev->ld_obd->obd_name, rc);
221 seq_printf(p, "- %-8s %llu\n", "id:", *((__u64 *)key));
222 seq_printf(p, " %-8s { inodes: %20"LPF64"u, bytes: %20"LPF64"u }\n",
223 "usage:", rec.ispace, rec.bspace);
227 struct seq_operations lprocfs_quota_seq_sops = {
228 .start = lprocfs_quota_seq_start,
229 .stop = lprocfs_quota_seq_stop,
230 .next = lprocfs_quota_seq_next,
231 .show = lprocfs_quota_seq_show,
234 static int lprocfs_quota_seq_open(struct inode *inode, struct file *file)
236 struct proc_dir_entry *dp = PDE(inode);
237 struct seq_file *seq;
239 struct lquota_procfs *lqp;
241 /* Allocate quota procfs data. This structure will be passed to
242 * seq_start/stop/next/show via seq->private */
247 /* store pointer to object we would like to iterate over */
248 lqp->lqp_obj = (struct dt_object *)dp->data;
250 /* Initialize the common environment to be used in the seq operations */
251 rc = lu_env_init(&lqp->lqp_env, LCT_LOCAL);
253 CERROR("%s: error initializing procfs quota env: rc = %d\n",
254 lqp->lqp_obj->do_lu.lo_dev->ld_obd->obd_name, rc);
258 if (LPROCFS_ENTRY_AND_CHECK(dp)) {
263 rc = seq_open(file, &lprocfs_quota_seq_sops);
267 seq = file->private_data;
274 lu_env_fini(&lqp->lqp_env);
280 static int lprocfs_quota_seq_release(struct inode *inode, struct file *file)
282 struct seq_file *seq = file->private_data;
283 struct lquota_procfs *lqp = seq->private;
288 lu_env_fini(&lqp->lqp_env);
291 return seq_release(inode, file);
294 struct file_operations lprocfs_quota_seq_fops = {
295 .owner = THIS_MODULE,
296 .open = lprocfs_quota_seq_open,
299 .release = lprocfs_quota_seq_release,
302 int lprocfs_quota_rd_type_dumb(char *page, char **start, off_t off, int count,
303 int *eof, void *data)
307 EXPORT_SYMBOL(lprocfs_quota_rd_type_dumb);
309 int lprocfs_quota_wr_type_dumb(struct file *file, const char *buffer,
310 unsigned long count, void *data)
314 EXPORT_SYMBOL(lprocfs_quota_wr_type_dumb);
316 int lprocfs_quota_rd_bunit(char *page, char **start, off_t off, int count,
317 int *eof, void *data)
319 struct obd_device *obd = (struct obd_device *)data;
320 LASSERT(obd != NULL);
322 return snprintf(page, count, "%lu\n",
323 obd->u.obt.obt_qctxt.lqc_bunit_sz);
325 EXPORT_SYMBOL(lprocfs_quota_rd_bunit);
327 int lprocfs_quota_wr_bunit(struct file *file, const char *buffer,
328 unsigned long count, void *data)
330 struct obd_device *obd = (struct obd_device *)data;
332 LASSERT(obd != NULL);
334 rc = lprocfs_write_helper(buffer, count, &val);
338 if (val % QUOTABLOCK_SIZE ||
339 val <= obd->u.obt.obt_qctxt.lqc_btune_sz)
342 obd->u.obt.obt_qctxt.lqc_bunit_sz = val;
345 EXPORT_SYMBOL(lprocfs_quota_wr_bunit);
347 int lprocfs_quota_rd_btune(char *page, char **start, off_t off, int count,
348 int *eof, void *data)
350 struct obd_device *obd = (struct obd_device *)data;
351 LASSERT(obd != NULL);
353 return snprintf(page, count, "%lu\n",
354 obd->u.obt.obt_qctxt.lqc_btune_sz);
356 EXPORT_SYMBOL(lprocfs_quota_rd_btune);
358 int lprocfs_quota_wr_btune(struct file *file, const char *buffer,
359 unsigned long count, void *data)
361 struct obd_device *obd = (struct obd_device *)data;
363 LASSERT(obd != NULL);
365 rc = lprocfs_write_helper(buffer, count, &val);
369 if (val <= QUOTABLOCK_SIZE * MIN_QLIMIT || val % QUOTABLOCK_SIZE ||
370 val >= obd->u.obt.obt_qctxt.lqc_bunit_sz)
373 obd->u.obt.obt_qctxt.lqc_btune_sz = val;
376 EXPORT_SYMBOL(lprocfs_quota_wr_btune);
378 int lprocfs_quota_rd_iunit(char *page, char **start, off_t off, int count,
379 int *eof, void *data)
381 struct obd_device *obd = (struct obd_device *)data;
382 LASSERT(obd != NULL);
384 return snprintf(page, count, "%lu\n",
385 obd->u.obt.obt_qctxt.lqc_iunit_sz);
387 EXPORT_SYMBOL(lprocfs_quota_rd_iunit);
389 int lprocfs_quota_wr_iunit(struct file *file, const char *buffer,
390 unsigned long count, void *data)
392 struct obd_device *obd = (struct obd_device *)data;
394 LASSERT(obd != NULL);
396 rc = lprocfs_write_helper(buffer, count, &val);
400 if (val <= obd->u.obt.obt_qctxt.lqc_itune_sz)
403 obd->u.obt.obt_qctxt.lqc_iunit_sz = val;
406 EXPORT_SYMBOL(lprocfs_quota_wr_iunit);
408 int lprocfs_quota_rd_itune(char *page, char **start, off_t off, int count,
409 int *eof, void *data)
411 struct obd_device *obd = (struct obd_device *)data;
412 LASSERT(obd != NULL);
414 return snprintf(page, count, "%lu\n",
415 obd->u.obt.obt_qctxt.lqc_itune_sz);
417 EXPORT_SYMBOL(lprocfs_quota_rd_itune);
419 int lprocfs_quota_wr_itune(struct file *file, const char *buffer,
420 unsigned long count, void *data)
422 struct obd_device *obd = (struct obd_device *)data;
424 LASSERT(obd != NULL);
426 rc = lprocfs_write_helper(buffer, count, &val);
430 if (val <= MIN_QLIMIT ||
431 val >= obd->u.obt.obt_qctxt.lqc_iunit_sz)
434 obd->u.obt.obt_qctxt.lqc_itune_sz = val;
437 EXPORT_SYMBOL(lprocfs_quota_wr_itune);
440 #define GROUP_QUOTA 2
442 #define MAX_STYPE_SIZE 5
444 int lprocfs_quota_rd_type(char *page, char **start, off_t off, int count,
445 int *eof, void *data)
447 struct obd_device *obd = (struct obd_device *)data;
448 char stype[MAX_STYPE_SIZE + 1] = "";
451 LASSERT(obd != NULL);
453 /* Collect the needed information */
454 oq_type = obd->u.obt.obt_qctxt.lqc_flags;
456 /* Transform the collected data into a user-readable string */
457 if (oq_type & LQC_USRQUOTA_FLAG)
459 if (oq_type & LQC_GRPQUOTA_FLAG)
464 return snprintf(page, count, "%s\n", stype);
466 EXPORT_SYMBOL(lprocfs_quota_rd_type);
469 * generic_quota_on is very lazy and tolerant about current quota settings
470 * @global means to turn on quotas on each OST additionally to local quotas;
471 * should not be called from filter_quota_ctl on MDS nodes (as it starts
472 * admin quotas on MDS nodes).
474 int generic_quota_on(struct obd_device *obd, struct obd_quotactl *oqctl, int global)
476 struct obd_device_target *obt = &obd->u.obt;
477 struct lvfs_run_ctxt saved;
478 int id, is_master, rc = 0, local; /* means we need a local quotaon */
480 cfs_down(&obt->obt_quotachecking);
481 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
482 id = UGQUOTA2LQC(oqctl->qc_type);
483 local = (obt->obt_qctxt.lqc_flags & id) != id;
485 oqctl->qc_cmd = Q_QUOTAON;
486 oqctl->qc_id = obt->obt_qfmt;
488 is_master = !strcmp(obd->obd_type->typ_name, LUSTRE_MDS_NAME);
490 cfs_down_write(&obd->u.mds.mds_qonoff_sem);
492 /* turn on cluster wide quota */
493 rc = mds_admin_quota_on(obd, oqctl);
494 if (rc && rc != -ENOENT)
495 CERROR("%s: %s admin quotaon failed. rc=%d\n",
496 obd->obd_name, global ? "global":"local",
503 rc = fsfilt_quotactl(obd, obt->obt_sb, oqctl);
506 CERROR("%s: %s quotaon failed with"
507 " rc=%d\n", obd->obd_name,
508 global ? "global" : "local", rc);
510 obt->obt_qctxt.lqc_flags |= UGQUOTA2LQC(oqctl->qc_type);
515 if (rc == 0 && global && is_master)
516 rc = obd_quotactl(obd->u.mds.mds_lov_exp, oqctl);
520 cfs_up_write(&obd->u.mds.mds_qonoff_sem);
522 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
523 cfs_up(&obt->obt_quotachecking);
525 CDEBUG(D_QUOTA, "%s: quotaon type:master:global:local:flags:rc "
526 "%u:%d:%d:%d:%lu:%d\n",
527 obd->obd_name, oqctl->qc_type, is_master, global, local,
528 obt->obt_qctxt.lqc_flags, rc);
533 static int auto_quota_on(struct obd_device *obd, int type)
535 struct obd_quotactl *oqctl;
539 LASSERT(type == USRQUOTA || type == GRPQUOTA || type == UGQUOTA);
541 OBD_ALLOC_PTR(oqctl);
545 oqctl->qc_type = type;
547 rc = generic_quota_on(obd, oqctl, 0);
553 int lprocfs_quota_wr_type(struct file *file, const char *buffer,
554 unsigned long count, void *data)
556 struct obd_device *obd = (struct obd_device *)data;
559 char stype[MAX_STYPE_SIZE + 1] = "";
561 LASSERT(obd != NULL);
563 if (count > MAX_STYPE_SIZE)
566 if (cfs_copy_from_user(stype, buffer, count))
569 for (i = 0 ; i < count ; i++) {
579 CWARN("quota_type options 1 and 2 are obsolete, "
580 "they will be ignored\n");
582 case '3' : /* the only valid version spec, do nothing */
583 default : /* just skip stray symbols like \n */
589 int rc = auto_quota_on(obd, type - 1);
591 if (rc && rc != -EALREADY && rc != -ENOENT)
597 EXPORT_SYMBOL(lprocfs_quota_wr_type);
599 int lprocfs_quota_rd_switch_seconds(char *page, char **start, off_t off,
600 int count, int *eof, void *data)
602 struct obd_device *obd = (struct obd_device *)data;
603 LASSERT(obd != NULL);
605 return snprintf(page, count, "%d\n",
606 obd->u.obt.obt_qctxt.lqc_switch_seconds);
608 EXPORT_SYMBOL(lprocfs_quota_rd_switch_seconds);
610 int lprocfs_quota_wr_switch_seconds(struct file *file, const char *buffer,
611 unsigned long count, void *data)
613 struct obd_device *obd = (struct obd_device *)data;
615 LASSERT(obd != NULL);
617 rc = lprocfs_write_helper(buffer, count, &val);
624 obd->u.obt.obt_qctxt.lqc_switch_seconds = val;
627 EXPORT_SYMBOL(lprocfs_quota_wr_switch_seconds);
629 int lprocfs_quota_rd_sync_blk(char *page, char **start, off_t off,
630 int count, int *eof, void *data)
632 struct obd_device *obd = (struct obd_device *)data;
633 LASSERT(obd != NULL);
635 return snprintf(page, count, "%d\n",
636 obd->u.obt.obt_qctxt.lqc_sync_blk);
638 EXPORT_SYMBOL(lprocfs_quota_rd_sync_blk);
640 int lprocfs_quota_wr_sync_blk(struct file *file, const char *buffer,
641 unsigned long count, void *data)
643 struct obd_device *obd = (struct obd_device *)data;
645 LASSERT(obd != NULL);
647 rc = lprocfs_write_helper(buffer, count, &val);
654 obd->u.obt.obt_qctxt.lqc_sync_blk = val;
657 EXPORT_SYMBOL(lprocfs_quota_wr_sync_blk);
659 int lprocfs_quota_rd_switch_qs(char *page, char **start, off_t off,
660 int count, int *eof, void *data)
662 struct obd_device *obd = (struct obd_device *)data;
663 LASSERT(obd != NULL);
665 return snprintf(page, count, "changing qunit size is %s\n",
666 obd->u.obt.obt_qctxt.lqc_switch_qs ?
667 "enabled" : "disabled");
669 EXPORT_SYMBOL(lprocfs_quota_rd_switch_qs);
671 int lprocfs_quota_wr_switch_qs(struct file *file, const char *buffer,
672 unsigned long count, void *data)
674 struct obd_device *obd = (struct obd_device *)data;
676 LASSERT(obd != NULL);
678 rc = lprocfs_write_helper(buffer, count, &val);
683 obd->u.obt.obt_qctxt.lqc_switch_qs = 1;
685 obd->u.obt.obt_qctxt.lqc_switch_qs = 0;
689 EXPORT_SYMBOL(lprocfs_quota_wr_switch_qs);
691 int lprocfs_quota_rd_boundary_factor(char *page, char **start, off_t off,
692 int count, int *eof, void *data)
694 struct obd_device *obd = (struct obd_device *)data;
695 LASSERT(obd != NULL);
698 return snprintf(page, count, "%lu\n",
699 obd->u.obt.obt_qctxt.lqc_cqs_boundary_factor);
701 EXPORT_SYMBOL(lprocfs_quota_rd_boundary_factor);
703 int lprocfs_quota_wr_boundary_factor(struct file *file, const char *buffer,
704 unsigned long count, void *data)
706 struct obd_device *obd = (struct obd_device *)data;
708 LASSERT(obd != NULL);
710 rc = lprocfs_write_helper(buffer, count, &val);
717 obd->u.obt.obt_qctxt.lqc_cqs_boundary_factor = val;
720 EXPORT_SYMBOL(lprocfs_quota_wr_boundary_factor);
722 int lprocfs_quota_rd_least_bunit(char *page, char **start, off_t off,
723 int count, int *eof, void *data)
725 struct obd_device *obd = (struct obd_device *)data;
726 LASSERT(obd != NULL);
729 return snprintf(page, count, "%lu\n",
730 obd->u.obt.obt_qctxt.lqc_cqs_least_bunit);
732 EXPORT_SYMBOL(lprocfs_quota_rd_least_bunit);
734 int lprocfs_quota_wr_least_bunit(struct file *file, const char *buffer,
735 unsigned long count, void *data)
737 struct obd_device *obd = (struct obd_device *)data;
739 LASSERT(obd != NULL);
741 rc = lprocfs_write_helper(buffer, count, &val);
745 if (val < PTLRPC_MAX_BRW_SIZE ||
746 val >= obd->u.obt.obt_qctxt.lqc_bunit_sz)
749 obd->u.obt.obt_qctxt.lqc_cqs_least_bunit = val;
752 EXPORT_SYMBOL(lprocfs_quota_wr_least_bunit);
754 int lprocfs_quota_rd_least_iunit(char *page, char **start, off_t off,
755 int count, int *eof, void *data)
757 struct obd_device *obd = (struct obd_device *)data;
758 LASSERT(obd != NULL);
761 return snprintf(page, count, "%lu\n",
762 obd->u.obt.obt_qctxt.lqc_cqs_least_iunit);
764 EXPORT_SYMBOL(lprocfs_quota_rd_least_iunit);
766 int lprocfs_quota_wr_least_iunit(struct file *file, const char *buffer,
767 unsigned long count, void *data)
769 struct obd_device *obd = (struct obd_device *)data;
771 LASSERT(obd != NULL);
773 rc = lprocfs_write_helper(buffer, count, &val);
777 if (val < 1 || val >= obd->u.obt.obt_qctxt.lqc_iunit_sz)
780 obd->u.obt.obt_qctxt.lqc_cqs_least_iunit = val;
783 EXPORT_SYMBOL(lprocfs_quota_wr_least_iunit);
785 int lprocfs_quota_rd_qs_factor(char *page, char **start, off_t off,
786 int count, int *eof, void *data)
788 struct obd_device *obd = (struct obd_device *)data;
789 LASSERT(obd != NULL);
792 return snprintf(page, count, "%lu\n",
793 obd->u.obt.obt_qctxt.lqc_cqs_qs_factor);
795 EXPORT_SYMBOL(lprocfs_quota_rd_qs_factor);
797 int lprocfs_quota_wr_qs_factor(struct file *file, const char *buffer,
798 unsigned long count, void *data)
800 struct obd_device *obd = (struct obd_device *)data;
802 LASSERT(obd != NULL);
804 rc = lprocfs_write_helper(buffer, count, &val);
811 obd->u.obt.obt_qctxt.lqc_cqs_qs_factor = val;
814 EXPORT_SYMBOL(lprocfs_quota_wr_qs_factor);
816 struct lprocfs_vars lprocfs_quota_common_vars[] = {
817 { "quota_bunit_sz", lprocfs_quota_rd_bunit,
818 lprocfs_quota_wr_bunit, 0},
819 { "quota_btune_sz", lprocfs_quota_rd_btune,
820 lprocfs_quota_wr_btune, 0},
821 { "quota_iunit_sz", lprocfs_quota_rd_iunit,
822 lprocfs_quota_wr_iunit, 0},
823 { "quota_itune_sz", lprocfs_quota_rd_itune,
824 lprocfs_quota_wr_itune, 0},
825 { "quota_type", lprocfs_quota_rd_type,
826 lprocfs_quota_wr_type, 0},
827 { "quota_switch_seconds", lprocfs_quota_rd_switch_seconds,
828 lprocfs_quota_wr_switch_seconds, 0 },
829 { "quota_sync_blk", lprocfs_quota_rd_sync_blk,
830 lprocfs_quota_wr_sync_blk, 0},
834 struct lprocfs_vars lprocfs_quota_master_vars[] = {
835 { "quota_switch_qs", lprocfs_quota_rd_switch_qs,
836 lprocfs_quota_wr_switch_qs, 0 },
837 { "quota_boundary_factor", lprocfs_quota_rd_boundary_factor,
838 lprocfs_quota_wr_boundary_factor, 0 },
839 { "quota_least_bunit", lprocfs_quota_rd_least_bunit,
840 lprocfs_quota_wr_least_bunit, 0 },
841 { "quota_least_iunit", lprocfs_quota_rd_least_iunit,
842 lprocfs_quota_wr_least_iunit, 0 },
843 { "quota_qs_factor", lprocfs_quota_rd_qs_factor,
844 lprocfs_quota_wr_qs_factor, 0 },
848 int lquota_proc_setup(struct obd_device *obd, int is_master)
850 struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt;
854 LASSERT(lquota_type_proc_dir && obd);
855 qctxt->lqc_proc_dir = lprocfs_register(obd->obd_name,
856 lquota_type_proc_dir,
857 lprocfs_quota_common_vars, obd);
858 if (IS_ERR(qctxt->lqc_proc_dir)) {
859 rc = PTR_ERR(qctxt->lqc_proc_dir);
860 CERROR("%s: error %d setting up lprocfs\n",
862 qctxt->lqc_proc_dir = NULL;
867 rc = lprocfs_add_vars(qctxt->lqc_proc_dir,
868 lprocfs_quota_master_vars, obd);
870 CERROR("%s: error %d setting up lprocfs for "
871 "quota master\n", obd->obd_name, rc);
872 GOTO(out_free_proc, rc);
876 qctxt->lqc_stats = lprocfs_alloc_stats(LQUOTA_LAST_STAT -
877 LQUOTA_FIRST_STAT, 0);
878 if (!qctxt->lqc_stats)
879 GOTO(out_free_proc, rc = -ENOMEM);
881 lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_SYNC_ACQ,
882 LPROCFS_CNTR_AVGMINMAX, "sync_acq_req", "us");
883 lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_SYNC_REL,
884 LPROCFS_CNTR_AVGMINMAX, "sync_rel_req", "us");
885 lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_ASYNC_ACQ,
886 LPROCFS_CNTR_AVGMINMAX, "async_acq_req", "us");
887 lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_ASYNC_REL,
888 LPROCFS_CNTR_AVGMINMAX, "async_rel_req", "us");
890 lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_FOR_CHK_BLK,
891 LPROCFS_CNTR_AVGMINMAX,
892 "wait_for_blk_quota(lquota_chkquota)", "us");
893 lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_FOR_CHK_INO,
894 LPROCFS_CNTR_AVGMINMAX,
895 "wait_for_ino_quota(lquota_chkquota)", "us");
896 lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_FOR_COMMIT_BLK,
897 LPROCFS_CNTR_AVGMINMAX,
898 "wait_for_blk_quota(lquota_pending_commit)",
900 lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_FOR_COMMIT_INO,
901 LPROCFS_CNTR_AVGMINMAX,
902 "wait_for_ino_quota(lquota_pending_commit)",
905 lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_PENDING_BLK_QUOTA,
906 LPROCFS_CNTR_AVGMINMAX,
907 "wait_for_pending_blk_quota_req"
908 "(qctxt_wait_pending_dqacq)", "us");
909 lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_PENDING_INO_QUOTA,
910 LPROCFS_CNTR_AVGMINMAX,
911 "wait_for_pending_ino_quota_req"
912 "(qctxt_wait_pending_dqacq)", "us");
913 lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_NOWAIT_PENDING_BLK_QUOTA,
914 LPROCFS_CNTR_AVGMINMAX,
915 "nowait_for_pending_blk_quota_req"
916 "(qctxt_wait_pending_dqacq)", "us");
917 lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_NOWAIT_PENDING_INO_QUOTA,
918 LPROCFS_CNTR_AVGMINMAX,
919 "nowait_for_pending_ino_quota_req"
920 "(qctxt_wait_pending_dqacq)", "us");
922 lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_QUOTA_CTL,
923 LPROCFS_CNTR_AVGMINMAX, "quota_ctl", "us");
924 lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_ADJUST_QUNIT,
925 LPROCFS_CNTR_AVGMINMAX, "adjust_qunit", "us");
927 lprocfs_register_stats(qctxt->lqc_proc_dir, "stats", qctxt->lqc_stats);
932 lprocfs_remove(&qctxt->lqc_proc_dir);
937 int lquota_proc_cleanup(struct lustre_quota_ctxt *qctxt)
939 if (!qctxt || !qctxt->lqc_proc_dir)
942 if (qctxt->lqc_stats != NULL)
943 lprocfs_free_stats(&qctxt->lqc_stats);
945 lprocfs_remove(&qctxt->lqc_proc_dir);