1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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
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
29 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
30 * Use is subject to license terms.
32 * Copyright (c) 2011, Whamcloud, Inc.
35 * This file is part of Lustre, http://www.lustre.org/
36 * Lustre is a trademark of Sun Microsystems, Inc.
39 #define DEBUG_SUBSYSTEM S_LQUOTA
41 #include <linux/version.h>
42 #include <lprocfs_status.h>
44 #include <linux/seq_file.h>
45 #include <lustre_fsfilt.h>
47 #include "quota_internal.h"
49 #ifdef HAVE_QUOTA_SUPPORT
52 int lprocfs_quota_rd_bunit(char *page, char **start, off_t off, int count,
55 struct obd_device *obd = (struct obd_device *)data;
58 return snprintf(page, count, "%lu\n",
59 obd->u.obt.obt_qctxt.lqc_bunit_sz);
61 EXPORT_SYMBOL(lprocfs_quota_rd_bunit);
63 int lprocfs_quota_wr_bunit(struct file *file, const char *buffer,
64 unsigned long count, void *data)
66 struct obd_device *obd = (struct obd_device *)data;
70 rc = lprocfs_write_helper(buffer, count, &val);
74 if (val % QUOTABLOCK_SIZE ||
75 val <= obd->u.obt.obt_qctxt.lqc_btune_sz)
78 obd->u.obt.obt_qctxt.lqc_bunit_sz = val;
81 EXPORT_SYMBOL(lprocfs_quota_wr_bunit);
83 int lprocfs_quota_rd_btune(char *page, char **start, off_t off, int count,
86 struct obd_device *obd = (struct obd_device *)data;
89 return snprintf(page, count, "%lu\n",
90 obd->u.obt.obt_qctxt.lqc_btune_sz);
92 EXPORT_SYMBOL(lprocfs_quota_rd_btune);
94 int lprocfs_quota_wr_btune(struct file *file, const char *buffer,
95 unsigned long count, void *data)
97 struct obd_device *obd = (struct obd_device *)data;
101 rc = lprocfs_write_helper(buffer, count, &val);
105 if (val <= QUOTABLOCK_SIZE * MIN_QLIMIT || val % QUOTABLOCK_SIZE ||
106 val >= obd->u.obt.obt_qctxt.lqc_bunit_sz)
109 obd->u.obt.obt_qctxt.lqc_btune_sz = val;
112 EXPORT_SYMBOL(lprocfs_quota_wr_btune);
114 int lprocfs_quota_rd_iunit(char *page, char **start, off_t off, int count,
115 int *eof, void *data)
117 struct obd_device *obd = (struct obd_device *)data;
118 LASSERT(obd != NULL);
120 return snprintf(page, count, "%lu\n",
121 obd->u.obt.obt_qctxt.lqc_iunit_sz);
123 EXPORT_SYMBOL(lprocfs_quota_rd_iunit);
125 int lprocfs_quota_wr_iunit(struct file *file, const char *buffer,
126 unsigned long count, void *data)
128 struct obd_device *obd = (struct obd_device *)data;
130 LASSERT(obd != NULL);
132 rc = lprocfs_write_helper(buffer, count, &val);
136 if (val <= obd->u.obt.obt_qctxt.lqc_itune_sz)
139 obd->u.obt.obt_qctxt.lqc_iunit_sz = val;
142 EXPORT_SYMBOL(lprocfs_quota_wr_iunit);
144 int lprocfs_quota_rd_itune(char *page, char **start, off_t off, int count,
145 int *eof, void *data)
147 struct obd_device *obd = (struct obd_device *)data;
148 LASSERT(obd != NULL);
150 return snprintf(page, count, "%lu\n",
151 obd->u.obt.obt_qctxt.lqc_itune_sz);
153 EXPORT_SYMBOL(lprocfs_quota_rd_itune);
155 int lprocfs_quota_wr_itune(struct file *file, const char *buffer,
156 unsigned long count, void *data)
158 struct obd_device *obd = (struct obd_device *)data;
160 LASSERT(obd != NULL);
162 rc = lprocfs_write_helper(buffer, count, &val);
166 if (val <= MIN_QLIMIT ||
167 val >= obd->u.obt.obt_qctxt.lqc_iunit_sz)
170 obd->u.obt.obt_qctxt.lqc_itune_sz = val;
173 EXPORT_SYMBOL(lprocfs_quota_wr_itune);
176 #define GROUP_QUOTA 2
178 #define MAX_STYPE_SIZE 5
180 int lprocfs_quota_rd_type(char *page, char **start, off_t off, int count,
181 int *eof, void *data)
183 struct obd_device *obd = (struct obd_device *)data;
184 char stype[MAX_STYPE_SIZE + 1] = "";
187 LASSERT(obd != NULL);
189 /* Collect the needed information */
190 oq_type = obd->u.obt.obt_qctxt.lqc_flags;
192 /* Transform the collected data into a user-readable string */
193 if (oq_type & LQC_USRQUOTA_FLAG)
195 if (oq_type & LQC_GRPQUOTA_FLAG)
200 return snprintf(page, count, "%s\n", stype);
202 EXPORT_SYMBOL(lprocfs_quota_rd_type);
205 * generic_quota_on is very lazy and tolerant about current quota settings
206 * @global means to turn on quotas on each OST additionally to local quotas;
207 * should not be called from filter_quota_ctl on MDS nodes (as it starts
208 * admin quotas on MDS nodes).
210 int generic_quota_on(struct obd_device *obd, struct obd_quotactl *oqctl, int global)
212 struct obd_device_target *obt = &obd->u.obt;
213 struct lvfs_run_ctxt saved;
214 int id, is_master, rc = 0, local; /* means we need a local quotaon */
216 cfs_down(&obt->obt_quotachecking);
217 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
218 id = UGQUOTA2LQC(oqctl->qc_type);
219 local = (obt->obt_qctxt.lqc_flags & id) != id;
221 oqctl->qc_cmd = Q_QUOTAON;
222 oqctl->qc_id = obt->obt_qfmt;
224 is_master = !strcmp(obd->obd_type->typ_name, LUSTRE_MDS_NAME);
226 cfs_down_write(&obd->u.mds.mds_qonoff_sem);
228 /* turn on cluster wide quota */
229 rc = mds_admin_quota_on(obd, oqctl);
230 if (rc && rc != -ENOENT)
231 CERROR("%s: %s admin quotaon failed. rc=%d\n",
232 obd->obd_name, global ? "global":"local",
239 rc = fsfilt_quotactl(obd, obt->obt_sb, oqctl);
242 CERROR("%s: %s quotaon failed with"
243 " rc=%d\n", obd->obd_name,
244 global ? "global" : "local", rc);
246 obt->obt_qctxt.lqc_flags |= UGQUOTA2LQC(oqctl->qc_type);
251 if (rc == 0 && global && is_master)
252 rc = obd_quotactl(obd->u.mds.mds_lov_exp, oqctl);
256 cfs_up_write(&obd->u.mds.mds_qonoff_sem);
258 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
259 cfs_up(&obt->obt_quotachecking);
261 CDEBUG(D_QUOTA, "%s: quotaon type:master:global:local:flags:rc "
262 "%u:%d:%d:%d:%lu:%d\n",
263 obd->obd_name, oqctl->qc_type, is_master, global, local,
264 obt->obt_qctxt.lqc_flags, rc);
269 static int auto_quota_on(struct obd_device *obd, int type)
271 struct obd_quotactl *oqctl;
275 LASSERT(type == USRQUOTA || type == GRPQUOTA || type == UGQUOTA);
277 OBD_ALLOC_PTR(oqctl);
281 oqctl->qc_type = type;
283 rc = generic_quota_on(obd, oqctl, 0);
289 int lprocfs_quota_wr_type(struct file *file, const char *buffer,
290 unsigned long count, void *data)
292 struct obd_device *obd = (struct obd_device *)data;
295 char stype[MAX_STYPE_SIZE + 1] = "";
297 LASSERT(obd != NULL);
299 if (count > MAX_STYPE_SIZE)
302 if (cfs_copy_from_user(stype, buffer, count))
305 for (i = 0 ; i < count ; i++) {
315 CWARN("quota_type options 1 and 2 are obsolete, "
316 "they will be ignored\n");
318 case '3' : /* the only valid version spec, do nothing */
319 default : /* just skip stray symbols like \n */
325 int rc = auto_quota_on(obd, type - 1);
327 if (rc && rc != -EALREADY && rc != -ENOENT)
333 EXPORT_SYMBOL(lprocfs_quota_wr_type);
335 int lprocfs_quota_rd_switch_seconds(char *page, char **start, off_t off,
336 int count, int *eof, void *data)
338 struct obd_device *obd = (struct obd_device *)data;
339 LASSERT(obd != NULL);
341 return snprintf(page, count, "%d\n",
342 obd->u.obt.obt_qctxt.lqc_switch_seconds);
344 EXPORT_SYMBOL(lprocfs_quota_rd_switch_seconds);
346 int lprocfs_quota_wr_switch_seconds(struct file *file, const char *buffer,
347 unsigned long count, void *data)
349 struct obd_device *obd = (struct obd_device *)data;
351 LASSERT(obd != NULL);
353 rc = lprocfs_write_helper(buffer, count, &val);
360 obd->u.obt.obt_qctxt.lqc_switch_seconds = val;
363 EXPORT_SYMBOL(lprocfs_quota_wr_switch_seconds);
365 int lprocfs_quota_rd_sync_blk(char *page, char **start, off_t off,
366 int count, int *eof, void *data)
368 struct obd_device *obd = (struct obd_device *)data;
369 LASSERT(obd != NULL);
371 return snprintf(page, count, "%d\n",
372 obd->u.obt.obt_qctxt.lqc_sync_blk);
374 EXPORT_SYMBOL(lprocfs_quota_rd_sync_blk);
376 int lprocfs_quota_wr_sync_blk(struct file *file, const char *buffer,
377 unsigned long count, void *data)
379 struct obd_device *obd = (struct obd_device *)data;
381 LASSERT(obd != NULL);
383 rc = lprocfs_write_helper(buffer, count, &val);
390 obd->u.obt.obt_qctxt.lqc_sync_blk = val;
393 EXPORT_SYMBOL(lprocfs_quota_wr_sync_blk);
395 int lprocfs_quota_rd_switch_qs(char *page, char **start, off_t off,
396 int count, int *eof, void *data)
398 struct obd_device *obd = (struct obd_device *)data;
399 LASSERT(obd != NULL);
401 return snprintf(page, count, "changing qunit size is %s\n",
402 obd->u.obt.obt_qctxt.lqc_switch_qs ?
403 "enabled" : "disabled");
405 EXPORT_SYMBOL(lprocfs_quota_rd_switch_qs);
407 int lprocfs_quota_wr_switch_qs(struct file *file, const char *buffer,
408 unsigned long count, void *data)
410 struct obd_device *obd = (struct obd_device *)data;
412 LASSERT(obd != NULL);
414 rc = lprocfs_write_helper(buffer, count, &val);
419 obd->u.obt.obt_qctxt.lqc_switch_qs = 1;
421 obd->u.obt.obt_qctxt.lqc_switch_qs = 0;
425 EXPORT_SYMBOL(lprocfs_quota_wr_switch_qs);
427 int lprocfs_quota_rd_boundary_factor(char *page, char **start, off_t off,
428 int count, int *eof, void *data)
430 struct obd_device *obd = (struct obd_device *)data;
431 LASSERT(obd != NULL);
434 return snprintf(page, count, "%lu\n",
435 obd->u.obt.obt_qctxt.lqc_cqs_boundary_factor);
437 EXPORT_SYMBOL(lprocfs_quota_rd_boundary_factor);
439 int lprocfs_quota_wr_boundary_factor(struct file *file, const char *buffer,
440 unsigned long count, void *data)
442 struct obd_device *obd = (struct obd_device *)data;
444 LASSERT(obd != NULL);
446 rc = lprocfs_write_helper(buffer, count, &val);
453 obd->u.obt.obt_qctxt.lqc_cqs_boundary_factor = val;
456 EXPORT_SYMBOL(lprocfs_quota_wr_boundary_factor);
458 int lprocfs_quota_rd_least_bunit(char *page, char **start, off_t off,
459 int count, int *eof, void *data)
461 struct obd_device *obd = (struct obd_device *)data;
462 LASSERT(obd != NULL);
465 return snprintf(page, count, "%lu\n",
466 obd->u.obt.obt_qctxt.lqc_cqs_least_bunit);
468 EXPORT_SYMBOL(lprocfs_quota_rd_least_bunit);
470 int lprocfs_quota_wr_least_bunit(struct file *file, const char *buffer,
471 unsigned long count, void *data)
473 struct obd_device *obd = (struct obd_device *)data;
475 LASSERT(obd != NULL);
477 rc = lprocfs_write_helper(buffer, count, &val);
481 if (val < PTLRPC_MAX_BRW_SIZE ||
482 val >= obd->u.obt.obt_qctxt.lqc_bunit_sz)
485 obd->u.obt.obt_qctxt.lqc_cqs_least_bunit = val;
488 EXPORT_SYMBOL(lprocfs_quota_wr_least_bunit);
490 int lprocfs_quota_rd_least_iunit(char *page, char **start, off_t off,
491 int count, int *eof, void *data)
493 struct obd_device *obd = (struct obd_device *)data;
494 LASSERT(obd != NULL);
497 return snprintf(page, count, "%lu\n",
498 obd->u.obt.obt_qctxt.lqc_cqs_least_iunit);
500 EXPORT_SYMBOL(lprocfs_quota_rd_least_iunit);
502 int lprocfs_quota_wr_least_iunit(struct file *file, const char *buffer,
503 unsigned long count, void *data)
505 struct obd_device *obd = (struct obd_device *)data;
507 LASSERT(obd != NULL);
509 rc = lprocfs_write_helper(buffer, count, &val);
513 if (val < 1 || val >= obd->u.obt.obt_qctxt.lqc_iunit_sz)
516 obd->u.obt.obt_qctxt.lqc_cqs_least_iunit = val;
519 EXPORT_SYMBOL(lprocfs_quota_wr_least_iunit);
521 int lprocfs_quota_rd_qs_factor(char *page, char **start, off_t off,
522 int count, int *eof, void *data)
524 struct obd_device *obd = (struct obd_device *)data;
525 LASSERT(obd != NULL);
528 return snprintf(page, count, "%lu\n",
529 obd->u.obt.obt_qctxt.lqc_cqs_qs_factor);
531 EXPORT_SYMBOL(lprocfs_quota_rd_qs_factor);
533 int lprocfs_quota_wr_qs_factor(struct file *file, const char *buffer,
534 unsigned long count, void *data)
536 struct obd_device *obd = (struct obd_device *)data;
538 LASSERT(obd != NULL);
540 rc = lprocfs_write_helper(buffer, count, &val);
547 obd->u.obt.obt_qctxt.lqc_cqs_qs_factor = val;
550 EXPORT_SYMBOL(lprocfs_quota_wr_qs_factor);
552 struct lprocfs_vars lprocfs_quota_common_vars[] = {
553 { "quota_bunit_sz", lprocfs_quota_rd_bunit,
554 lprocfs_quota_wr_bunit, 0},
555 { "quota_btune_sz", lprocfs_quota_rd_btune,
556 lprocfs_quota_wr_btune, 0},
557 { "quota_iunit_sz", lprocfs_quota_rd_iunit,
558 lprocfs_quota_wr_iunit, 0},
559 { "quota_itune_sz", lprocfs_quota_rd_itune,
560 lprocfs_quota_wr_itune, 0},
561 { "quota_type", lprocfs_quota_rd_type,
562 lprocfs_quota_wr_type, 0},
563 { "quota_switch_seconds", lprocfs_quota_rd_switch_seconds,
564 lprocfs_quota_wr_switch_seconds, 0 },
565 { "quota_sync_blk", lprocfs_quota_rd_sync_blk,
566 lprocfs_quota_wr_sync_blk, 0},
570 struct lprocfs_vars lprocfs_quota_master_vars[] = {
571 { "quota_switch_qs", lprocfs_quota_rd_switch_qs,
572 lprocfs_quota_wr_switch_qs, 0 },
573 { "quota_boundary_factor", lprocfs_quota_rd_boundary_factor,
574 lprocfs_quota_wr_boundary_factor, 0 },
575 { "quota_least_bunit", lprocfs_quota_rd_least_bunit,
576 lprocfs_quota_wr_least_bunit, 0 },
577 { "quota_least_iunit", lprocfs_quota_rd_least_iunit,
578 lprocfs_quota_wr_least_iunit, 0 },
579 { "quota_qs_factor", lprocfs_quota_rd_qs_factor,
580 lprocfs_quota_wr_qs_factor, 0 },
584 int lquota_proc_setup(struct obd_device *obd, int is_master)
586 struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt;
590 LASSERT(lquota_type_proc_dir && obd);
591 qctxt->lqc_proc_dir = lprocfs_register(obd->obd_name,
592 lquota_type_proc_dir,
593 lprocfs_quota_common_vars, obd);
594 if (IS_ERR(qctxt->lqc_proc_dir)) {
595 rc = PTR_ERR(qctxt->lqc_proc_dir);
596 CERROR("%s: error %d setting up lprocfs\n",
598 qctxt->lqc_proc_dir = NULL;
603 rc = lprocfs_add_vars(qctxt->lqc_proc_dir,
604 lprocfs_quota_master_vars, obd);
606 CERROR("%s: error %d setting up lprocfs for "
607 "quota master\n", obd->obd_name, rc);
608 GOTO(out_free_proc, rc);
612 qctxt->lqc_stats = lprocfs_alloc_stats(LQUOTA_LAST_STAT -
613 LQUOTA_FIRST_STAT, 0);
614 if (!qctxt->lqc_stats)
615 GOTO(out_free_proc, rc = -ENOMEM);
617 lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_SYNC_ACQ,
618 LPROCFS_CNTR_AVGMINMAX, "sync_acq_req", "us");
619 lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_SYNC_REL,
620 LPROCFS_CNTR_AVGMINMAX, "sync_rel_req", "us");
621 lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_ASYNC_ACQ,
622 LPROCFS_CNTR_AVGMINMAX, "async_acq_req", "us");
623 lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_ASYNC_REL,
624 LPROCFS_CNTR_AVGMINMAX, "async_rel_req", "us");
626 lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_FOR_CHK_BLK,
627 LPROCFS_CNTR_AVGMINMAX,
628 "wait_for_blk_quota(lquota_chkquota)", "us");
629 lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_FOR_CHK_INO,
630 LPROCFS_CNTR_AVGMINMAX,
631 "wait_for_ino_quota(lquota_chkquota)", "us");
632 lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_FOR_COMMIT_BLK,
633 LPROCFS_CNTR_AVGMINMAX,
634 "wait_for_blk_quota(lquota_pending_commit)",
636 lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_FOR_COMMIT_INO,
637 LPROCFS_CNTR_AVGMINMAX,
638 "wait_for_ino_quota(lquota_pending_commit)",
641 lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_PENDING_BLK_QUOTA,
642 LPROCFS_CNTR_AVGMINMAX,
643 "wait_for_pending_blk_quota_req"
644 "(qctxt_wait_pending_dqacq)", "us");
645 lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_WAIT_PENDING_INO_QUOTA,
646 LPROCFS_CNTR_AVGMINMAX,
647 "wait_for_pending_ino_quota_req"
648 "(qctxt_wait_pending_dqacq)", "us");
649 lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_NOWAIT_PENDING_BLK_QUOTA,
650 LPROCFS_CNTR_AVGMINMAX,
651 "nowait_for_pending_blk_quota_req"
652 "(qctxt_wait_pending_dqacq)", "us");
653 lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_NOWAIT_PENDING_INO_QUOTA,
654 LPROCFS_CNTR_AVGMINMAX,
655 "nowait_for_pending_ino_quota_req"
656 "(qctxt_wait_pending_dqacq)", "us");
658 lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_QUOTA_CTL,
659 LPROCFS_CNTR_AVGMINMAX, "quota_ctl", "us");
660 lprocfs_counter_init(qctxt->lqc_stats, LQUOTA_ADJUST_QUNIT,
661 LPROCFS_CNTR_AVGMINMAX, "adjust_qunit", "us");
663 lprocfs_register_stats(qctxt->lqc_proc_dir, "stats", qctxt->lqc_stats);
668 lprocfs_remove(&qctxt->lqc_proc_dir);
673 int lquota_proc_cleanup(struct lustre_quota_ctxt *qctxt)
675 if (!qctxt || !qctxt->lqc_proc_dir)
678 if (qctxt->lqc_stats != NULL)
679 lprocfs_free_stats(&qctxt->lqc_stats);
681 lprocfs_remove(&qctxt->lqc_proc_dir);