1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * lustre/quota/quota_interface.c
6 * Copyright (c) 2001-2005 Cluster File Systems, Inc.
8 * This file is part of Lustre, http://www.lustre.org.
10 * No redistribution or use is permitted outside of Cluster File Systems, Inc.
14 # define EXPORT_SYMTAB
16 #define DEBUG_SUBSYSTEM S_MDS
19 # include <linux/version.h>
20 # include <linux/module.h>
21 # include <linux/init.h>
22 # include <linux/fs.h>
23 # include <linux/jbd.h>
24 # include <linux/ext3_fs.h>
25 # if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
26 # include <linux/smp_lock.h>
27 # include <linux/buffer_head.h>
28 # include <linux/workqueue.h>
29 # include <linux/mount.h>
31 # include <linux/locks.h>
33 #else /* __KERNEL__ */
34 # include <liblustre.h>
37 #include <obd_class.h>
38 #include <lustre_mds.h>
39 #include <lustre_dlm.h>
40 #include <lustre_cfg.h>
42 #include <lustre_fsfilt.h>
43 #include <lustre_quota.h>
44 #include <lprocfs_status.h>
45 #include "quota_internal.h"
50 /* quota proc file handling functions */
53 int lprocfs_quota_rd_bunit(char *page, char **start, off_t off, int count,
56 struct obd_device *obd = (struct obd_device *)data;
59 return snprintf(page, count, "%lu\n",
60 obd->u.obt.obt_qctxt.lqc_bunit_sz);
62 EXPORT_SYMBOL(lprocfs_quota_rd_bunit);
64 int lprocfs_quota_wr_bunit(struct file *file, const char *buffer,
65 unsigned long count, void *data)
67 struct obd_device *obd = (struct obd_device *)data;
71 rc = lprocfs_write_helper(buffer, count, &val);
75 if (val % QUOTABLOCK_SIZE ||
76 val <= obd->u.obt.obt_qctxt.lqc_btune_sz)
79 obd->u.obt.obt_qctxt.lqc_bunit_sz = val;
82 EXPORT_SYMBOL(lprocfs_quota_wr_bunit);
84 int lprocfs_quota_rd_btune(char *page, char **start, off_t off, int count,
87 struct obd_device *obd = (struct obd_device *)data;
90 return snprintf(page, count, "%lu\n",
91 obd->u.obt.obt_qctxt.lqc_btune_sz);
93 EXPORT_SYMBOL(lprocfs_quota_rd_btune);
95 int lprocfs_quota_wr_btune(struct file *file, const char *buffer,
96 unsigned long count, void *data)
98 struct obd_device *obd = (struct obd_device *)data;
100 LASSERT(obd != NULL);
102 rc = lprocfs_write_helper(buffer, count, &val);
106 if (val <= QUOTABLOCK_SIZE * MIN_QLIMIT || val % QUOTABLOCK_SIZE ||
107 val >= obd->u.obt.obt_qctxt.lqc_bunit_sz)
110 obd->u.obt.obt_qctxt.lqc_btune_sz = val;
113 EXPORT_SYMBOL(lprocfs_quota_wr_btune);
115 int lprocfs_quota_rd_iunit(char *page, char **start, off_t off, int count,
116 int *eof, void *data)
118 struct obd_device *obd = (struct obd_device *)data;
119 LASSERT(obd != NULL);
121 return snprintf(page, count, "%lu\n",
122 obd->u.obt.obt_qctxt.lqc_iunit_sz);
124 EXPORT_SYMBOL(lprocfs_quota_rd_iunit);
126 int lprocfs_quota_wr_iunit(struct file *file, const char *buffer,
127 unsigned long count, void *data)
129 struct obd_device *obd = (struct obd_device *)data;
131 LASSERT(obd != NULL);
133 rc = lprocfs_write_helper(buffer, count, &val);
137 if (val <= obd->u.obt.obt_qctxt.lqc_itune_sz)
140 obd->u.obt.obt_qctxt.lqc_iunit_sz = val;
143 EXPORT_SYMBOL(lprocfs_quota_wr_iunit);
145 int lprocfs_quota_rd_itune(char *page, char **start, off_t off, int count,
146 int *eof, void *data)
148 struct obd_device *obd = (struct obd_device *)data;
149 LASSERT(obd != NULL);
151 return snprintf(page, count, "%lu\n",
152 obd->u.obt.obt_qctxt.lqc_itune_sz);
154 EXPORT_SYMBOL(lprocfs_quota_rd_itune);
156 int lprocfs_quota_wr_itune(struct file *file, const char *buffer,
157 unsigned long count, void *data)
159 struct obd_device *obd = (struct obd_device *)data;
161 LASSERT(obd != NULL);
163 rc = lprocfs_write_helper(buffer, count, &val);
167 if (val <= MIN_QLIMIT ||
168 val >= obd->u.obt.obt_qctxt.lqc_iunit_sz)
171 obd->u.obt.obt_qctxt.lqc_itune_sz = val;
174 EXPORT_SYMBOL(lprocfs_quota_wr_itune);
176 int lprocfs_quota_rd_switch_seconds(char *page, char **start, off_t off,
177 int count, int *eof, void *data)
179 struct obd_device *obd = (struct obd_device *)data;
180 LASSERT(obd != NULL);
182 return snprintf(page, count, "%d\n",
183 obd->u.obt.obt_qctxt.lqc_switch_seconds);
185 EXPORT_SYMBOL(lprocfs_quota_rd_switch_seconds);
187 int lprocfs_quota_wr_switch_seconds(struct file *file, const char *buffer,
188 unsigned long count, void *data)
190 struct obd_device *obd = (struct obd_device *)data;
192 LASSERT(obd != NULL);
194 rc = lprocfs_write_helper(buffer, count, &val);
201 obd->u.obt.obt_qctxt.lqc_switch_seconds = val;
204 EXPORT_SYMBOL(lprocfs_quota_wr_switch_seconds);
207 #define GROUP_QUOTA 2
209 #define MAX_STYPE_SIZE 5
210 int lprocfs_quota_rd_type(char *page, char **start, off_t off, int count,
211 int *eof, void *data)
213 struct obd_device *obd = (struct obd_device *)data;
214 char stype[MAX_STYPE_SIZE + 1] = "";
215 int type = obd->u.obt.obt_qctxt.lqc_atype;
216 LASSERT(obd != NULL);
219 strcpy(stype, "off");
221 if (type & USER_QUOTA)
223 if (type & GROUP_QUOTA)
227 /* append with quota version on MDS */
228 if (!strcmp(obd->obd_type->typ_name, LUSTRE_MDS_NAME)) {
230 lustre_quota_version_t version;
232 rc = mds_quota_get_version(obd, &version);
237 case LUSTRE_QUOTA_V1:
240 case LUSTRE_QUOTA_V2:
248 return snprintf(page, count, "%s\n", stype);
250 EXPORT_SYMBOL(lprocfs_quota_rd_type);
252 static int auto_quota_on(struct obd_device *obd, int type,
253 struct super_block *sb, int is_master)
255 struct obd_quotactl *oqctl;
256 struct lvfs_run_ctxt saved;
260 LASSERT(type == USRQUOTA || type == GRPQUOTA || type == UGQUOTA);
262 /* quota already turned on */
263 if (obd->u.obt.obt_qctxt.lqc_status)
266 OBD_ALLOC_PTR(oqctl);
270 oqctl->qc_type = type;
271 oqctl->qc_cmd = Q_QUOTAON;
272 oqctl->qc_id = QFMT_LDISKFS;
274 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
279 /* turn on cluster wide quota */
280 rc = mds_admin_quota_on(obd, oqctl);
282 CDEBUG(rc == -ENOENT ? D_QUOTA : D_ERROR,
283 "auto-enable admin quota failed. rc=%d\n", rc);
287 /* turn on local quota */
288 rc = fsfilt_quotactl(obd, sb, oqctl);
290 CDEBUG(rc == -ENOENT ? D_QUOTA : D_ERROR,
291 "auto-enable local quota failed. rc=%d\n", rc);
293 mds_quota_off(obd, oqctl);
295 obd->u.obt.obt_qctxt.lqc_status = 1;
298 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
304 int lprocfs_quota_wr_type(struct file *file, const char *buffer,
305 unsigned long count, void *data)
307 struct obd_device *obd = (struct obd_device *)data;
308 struct obd_device_target *obt = &obd->u.obt;
311 char stype[MAX_STYPE_SIZE + 1] = "";
312 LASSERT(obd != NULL);
314 if (count > MAX_STYPE_SIZE)
317 if (copy_from_user(stype, buffer, count))
320 for (i = 0 ; i < count ; i++) {
330 /* quota version specifiers */
332 if (strcmp(obd->obd_type->typ_name, LUSTRE_MDS_NAME))
335 rc = mds_quota_set_version(obd, LUSTRE_QUOTA_V1);
337 CDEBUG(D_QUOTA, "failed to set quota v1! %d\n", rc);
342 if (strcmp(obd->obd_type->typ_name, LUSTRE_MDS_NAME))
345 rc = mds_quota_set_version(obd, LUSTRE_QUOTA_V2);
347 CDEBUG(D_QUOTA, "could not set quota v2! %d\n", rc);
351 default : /* just skip stray symbols like \n */
356 obt->obt_qctxt.lqc_atype = type;
361 if (!strcmp(obd->obd_type->typ_name, LUSTRE_MDS_NAME))
362 auto_quota_on(obd, type - 1, obt->obt_sb, 1);
363 else if (!strcmp(obd->obd_type->typ_name, LUSTRE_OST_NAME))
364 auto_quota_on(obd, type - 1, obt->obt_sb, 0);
370 EXPORT_SYMBOL(lprocfs_quota_wr_type);
375 static int filter_quota_setup(struct obd_device *obd)
378 struct obd_device_target *obt = &obd->u.obt;
381 atomic_set(&obt->obt_quotachecking, 1);
382 rc = qctxt_init(&obt->obt_qctxt, obt->obt_sb, NULL);
384 CERROR("initialize quota context failed! (rc:%d)\n", rc);
390 static int filter_quota_cleanup(struct obd_device *obd)
392 qctxt_cleanup(&obd->u.obt.obt_qctxt, 0);
396 static int filter_quota_setinfo(struct obd_export *exp, struct obd_device *obd)
398 struct obd_import *imp;
400 /* setup the quota context import */
401 spin_lock(&obd->u.obt.obt_qctxt.lqc_lock);
402 obd->u.obt.obt_qctxt.lqc_import = exp->exp_imp_reverse;
403 spin_unlock(&obd->u.obt.obt_qctxt.lqc_lock);
405 /* make imp's connect flags equal relative exp's connect flags
406 * adding it to avoid the scan export list
408 imp = exp->exp_imp_reverse;
410 imp->imp_connect_data.ocd_connect_flags |=
411 (exp->exp_connect_flags &
412 (OBD_CONNECT_QUOTA64 | OBD_CONNECT_CHANGE_QS));
414 /* start quota slave recovery thread. (release high limits) */
415 qslave_start_recovery(obd, &obd->u.obt.obt_qctxt);
419 static int filter_quota_clearinfo(struct obd_export *exp, struct obd_device *obd)
421 struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt;
423 /* when exp->exp_imp_reverse is destroyed, the corresponding lqc_import
424 * should be invalid b=12374 */
425 if (qctxt->lqc_import == exp->exp_imp_reverse) {
426 spin_lock(&qctxt->lqc_lock);
427 qctxt->lqc_import = NULL;
428 spin_unlock(&qctxt->lqc_lock);
434 static int filter_quota_enforce(struct obd_device *obd, unsigned int ignore)
438 if (!sb_any_quota_enabled(obd->u.obt.obt_sb))
442 cap_raise(current->cap_effective, CAP_SYS_RESOURCE);
444 cap_lower(current->cap_effective, CAP_SYS_RESOURCE);
449 static int filter_quota_getflag(struct obd_device *obd, struct obdo *oa)
451 struct obd_device_target *obt = &obd->u.obt;
452 int err, cnt, rc = 0;
453 struct obd_quotactl *oqctl;
456 if (!sb_any_quota_enabled(obt->obt_sb))
459 oa->o_flags &= ~(OBD_FL_NO_USRQUOTA | OBD_FL_NO_GRPQUOTA);
461 OBD_ALLOC_PTR(oqctl);
463 CERROR("Not enough memory!");
467 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
468 memset(oqctl, 0, sizeof(*oqctl));
470 oqctl->qc_cmd = Q_GETQUOTA;
471 oqctl->qc_type = cnt;
472 oqctl->qc_id = (cnt == USRQUOTA) ? oa->o_uid : oa->o_gid;
473 err = fsfilt_quotactl(obd, obt->obt_sb, oqctl);
480 /* set over quota flags for a uid/gid */
481 oa->o_valid |= (cnt == USRQUOTA) ?
482 OBD_MD_FLUSRQUOTA : OBD_MD_FLGRPQUOTA;
483 if (oqctl->qc_dqblk.dqb_bhardlimit &&
484 (toqb(oqctl->qc_dqblk.dqb_curspace) >
485 oqctl->qc_dqblk.dqb_bhardlimit))
486 oa->o_flags |= (cnt == USRQUOTA) ?
487 OBD_FL_NO_USRQUOTA : OBD_FL_NO_GRPQUOTA;
493 static int filter_quota_acquire(struct obd_device *obd, unsigned int uid,
496 struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt;
500 rc = qctxt_adjust_qunit(obd, qctxt, uid, gid, LQUOTA_FLAGS_BLK, 1);
504 /* check whether the left quota of certain uid and gid can satisfy a block_write
505 * or inode_create rpc. When need to acquire quota, return QUOTA_RET_ACQUOTA */
506 static int quota_check_common(struct obd_device *obd, unsigned int uid,
507 unsigned int gid, int count, int cycle, int isblk)
509 struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt;
511 __u32 id[MAXQUOTAS] = { uid, gid };
512 struct qunit_data qdata[MAXQUOTAS];
513 int rc = 0, rc2[2] = { 0, 0 };
516 CLASSERT(MAXQUOTAS < 4);
517 if (!sb_any_quota_enabled(qctxt->lqc_sb))
520 for (i = 0; i < MAXQUOTAS; i++) {
521 struct lustre_qunit_size *lqs = NULL;
523 qdata[i].qd_id = id[i];
524 qdata[i].qd_flags = i;
526 QDATA_SET_BLK(&qdata[i]);
527 qdata[i].qd_count = 0;
529 /* ignore root user */
530 if (qdata[i].qd_id == 0 && !QDATA_IS_GRP(&qdata[i]))
533 quota_search_lqs(&qdata[i], NULL, qctxt, &lqs);
537 qctxt_wait_pending_dqacq(qctxt, id[i], i, isblk);
538 rc2[i] = compute_remquota(obd, qctxt, &qdata[i], isblk);
539 spin_lock(&lqs->lqs_lock);
541 rc = QUOTA_RET_INC_PENDING;
543 lqs->lqs_bwrite_pending += count;
545 lqs->lqs_iwrite_pending += count;
548 CDEBUG(D_QUOTA, "write pending: %lu, qd_count: "LPU64".\n",
549 isblk ? lqs->lqs_bwrite_pending : lqs->lqs_iwrite_pending,
551 if (rc2[i] == QUOTA_RET_OK) {
552 if (isblk && qdata[i].qd_count <
553 lqs->lqs_bwrite_pending * CFS_PAGE_SIZE)
554 rc2[i] = QUOTA_RET_ACQUOTA;
555 if (!isblk && qdata[i].qd_count <
556 lqs->lqs_iwrite_pending)
557 rc2[i] = QUOTA_RET_ACQUOTA;
560 spin_unlock(&lqs->lqs_lock);
564 if (rc2[0] == QUOTA_RET_ACQUOTA || rc2[1] == QUOTA_RET_ACQUOTA)
565 RETURN(rc | QUOTA_RET_ACQUOTA);
570 static int quota_chk_acq_common(struct obd_device *obd, unsigned int uid,
571 unsigned int gid, int count, int *pending,
572 int isblk, quota_acquire acquire)
574 int rc = 0, cycle = 0;
577 while ((rc = quota_check_common(obd, uid, gid, count, cycle, isblk)) &
580 if (rc & QUOTA_RET_INC_PENDING)
585 OBD_FAIL_TIMEOUT(OBD_FAIL_OST_HOLD_WRITE_RPC, 90);
586 rc = acquire(obd, uid, gid);
588 /* please reference to dqacq_completion for the below */
589 /* a new request is finished, try again */
591 CDEBUG(D_QUOTA, "finish a quota req, try again\n");
595 /* it is out of quota already */
597 CDEBUG(D_QUOTA, "out of quota, return -EDQUOT\n");
601 /* -EBUSY and others, try 10 times */
602 if (rc < 0 && cycle < 10) {
603 CDEBUG(D_QUOTA, "rc: %d, cycle: %d\n", rc, cycle);
604 cfs_schedule_timeout(CFS_TASK_INTERRUPTIBLE, HZ);
608 CDEBUG(D_QUOTA, "exit with rc: %d\n", rc);
612 if (!cycle && rc & QUOTA_RET_INC_PENDING)
619 static int filter_quota_check(struct obd_device *obd, unsigned int uid,
620 unsigned int gid, int npage, int *flag,
621 quota_acquire acquire)
623 return quota_chk_acq_common(obd, uid, gid, npage, flag, LQUOTA_FLAGS_BLK,
627 /* when a block_write or inode_create rpc is finished, adjust the record for
628 * pending blocks and inodes*/
629 static int quota_pending_commit(struct obd_device *obd, unsigned int uid,
630 unsigned int gid, int count, int isblk)
632 struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt;
634 __u32 id[MAXQUOTAS] = { uid, gid };
635 struct qunit_data qdata[MAXQUOTAS];
638 CLASSERT(MAXQUOTAS < 4);
639 if (!sb_any_quota_enabled(qctxt->lqc_sb))
642 for (i = 0; i < MAXQUOTAS; i++) {
643 struct lustre_qunit_size *lqs = NULL;
645 qdata[i].qd_id = id[i];
646 qdata[i].qd_flags = i;
648 QDATA_SET_BLK(&qdata[i]);
649 qdata[i].qd_count = 0;
651 if (qdata[i].qd_id == 0 && !QDATA_IS_GRP(&qdata[i]))
654 quota_search_lqs(&qdata[i], NULL, qctxt, &lqs);
656 spin_lock(&lqs->lqs_lock);
657 CDEBUG(D_QUOTA, "pending: %lu, count: %d.\n",
658 isblk ? lqs->lqs_bwrite_pending :
659 lqs->lqs_iwrite_pending, count);
662 if (lqs->lqs_bwrite_pending >= count)
663 lqs->lqs_bwrite_pending -= count;
666 "there are too many blocks!\n");
668 if (lqs->lqs_iwrite_pending >= count)
669 lqs->lqs_iwrite_pending -= count;
672 "there are too many files!\n");
675 spin_unlock(&lqs->lqs_lock);
683 static int filter_quota_pending_commit(struct obd_device *obd, unsigned int uid,
684 unsigned int gid, int npage)
686 return quota_pending_commit(obd, uid, gid, npage, LQUOTA_FLAGS_BLK);
689 static int mds_quota_init(void)
691 return lustre_dquot_init();
694 static int mds_quota_exit(void)
700 static int mds_quota_setup(struct obd_device *obd)
702 struct obd_device_target *obt = &obd->u.obt;
703 struct mds_obd *mds = &obd->u.mds;
707 mds->mds_quota_info.qi_version = LUSTRE_QUOTA_V2;
708 atomic_set(&obt->obt_quotachecking, 1);
709 /* initialize quota master and quota context */
710 sema_init(&mds->mds_qonoff_sem, 1);
711 rc = qctxt_init(&obt->obt_qctxt, obt->obt_sb, dqacq_handler);
713 CERROR("initialize quota context failed! (rc:%d)\n", rc);
719 static int mds_quota_cleanup(struct obd_device *obd)
721 qctxt_cleanup(&obd->u.obt.obt_qctxt, 0);
725 static int mds_quota_fs_cleanup(struct obd_device *obd)
727 struct mds_obd *mds = &obd->u.mds;
731 /* close admin quota files */
732 down(&mds->mds_qonoff_sem);
733 for (i = 0; i < MAXQUOTAS; i++) {
734 if (mds->mds_quota_info.qi_files[i]) {
735 filp_close(mds->mds_quota_info.qi_files[i], 0);
736 mds->mds_quota_info.qi_files[i] = NULL;
739 up(&mds->mds_qonoff_sem);
743 static int mds_quota_check(struct obd_device *obd, unsigned int uid,
744 unsigned int gid, int inodes, int *flag,
745 quota_acquire acquire)
747 return quota_chk_acq_common(obd, uid, gid, inodes, flag, 0, acquire);
750 static int mds_quota_acquire(struct obd_device *obd, unsigned int uid,
753 struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt;
757 rc = qctxt_adjust_qunit(obd, qctxt, uid, gid, 0, 1);
761 static int mds_quota_pending_commit(struct obd_device *obd, unsigned int uid,
762 unsigned int gid, int inodes)
764 return quota_pending_commit(obd, uid, gid, inodes, 0);
766 #endif /* __KERNEL__ */
768 struct osc_quota_info {
769 struct list_head oqi_hash; /* hash list */
770 struct client_obd *oqi_cli; /* osc obd */
771 unsigned int oqi_id; /* uid/gid of a file */
772 short oqi_type; /* quota type */
775 spinlock_t qinfo_list_lock = SPIN_LOCK_UNLOCKED;
777 static struct list_head qinfo_hash[NR_DQHASH];
778 /* SLAB cache for client quota context */
779 cfs_mem_cache_t *qinfo_cachep = NULL;
781 static inline int hashfn(struct client_obd *cli, unsigned long id, int type)
782 __attribute__((__const__));
784 static inline int hashfn(struct client_obd *cli, unsigned long id, int type)
786 unsigned long tmp = ((unsigned long)cli>>6) ^ id;
787 tmp = (tmp * (MAXQUOTAS - type)) % NR_DQHASH;
791 /* caller must hold qinfo_list_lock */
792 static inline void insert_qinfo_hash(struct osc_quota_info *oqi)
794 struct list_head *head = qinfo_hash +
795 hashfn(oqi->oqi_cli, oqi->oqi_id, oqi->oqi_type);
797 LASSERT_SPIN_LOCKED(&qinfo_list_lock);
798 list_add(&oqi->oqi_hash, head);
801 /* caller must hold qinfo_list_lock */
802 static inline void remove_qinfo_hash(struct osc_quota_info *oqi)
804 LASSERT_SPIN_LOCKED(&qinfo_list_lock);
805 list_del_init(&oqi->oqi_hash);
808 /* caller must hold qinfo_list_lock */
809 static inline struct osc_quota_info *find_qinfo(struct client_obd *cli,
810 unsigned int id, int type)
812 unsigned int hashent = hashfn(cli, id, type);
813 struct osc_quota_info *oqi;
815 LASSERT_SPIN_LOCKED(&qinfo_list_lock);
816 list_for_each_entry(oqi, &qinfo_hash[hashent], oqi_hash) {
817 if (oqi->oqi_cli == cli &&
818 oqi->oqi_id == id && oqi->oqi_type == type)
824 static struct osc_quota_info *alloc_qinfo(struct client_obd *cli,
825 unsigned int id, int type)
827 struct osc_quota_info *oqi;
830 OBD_SLAB_ALLOC(oqi, qinfo_cachep, CFS_ALLOC_STD, sizeof(*oqi));
834 INIT_LIST_HEAD(&oqi->oqi_hash);
837 oqi->oqi_type = type;
842 static void free_qinfo(struct osc_quota_info *oqi)
844 OBD_SLAB_FREE(oqi, qinfo_cachep, sizeof(*oqi));
847 int osc_quota_chkdq(struct client_obd *cli,
848 unsigned int uid, unsigned int gid)
851 int cnt, rc = QUOTA_OK;
854 spin_lock(&qinfo_list_lock);
855 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
856 struct osc_quota_info *oqi = NULL;
858 id = (cnt == USRQUOTA) ? uid : gid;
859 oqi = find_qinfo(cli, id, cnt);
865 spin_unlock(&qinfo_list_lock);
870 int osc_quota_setdq(struct client_obd *cli,
871 unsigned int uid, unsigned int gid,
872 obd_flag valid, obd_flag flags)
880 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
881 struct osc_quota_info *oqi, *old;
883 if (!(valid & ((cnt == USRQUOTA) ?
884 OBD_MD_FLUSRQUOTA : OBD_MD_FLGRPQUOTA)))
887 id = (cnt == USRQUOTA) ? uid : gid;
888 noquota = (cnt == USRQUOTA) ?
889 (flags & OBD_FL_NO_USRQUOTA) : (flags & OBD_FL_NO_GRPQUOTA);
891 oqi = alloc_qinfo(cli, id, cnt);
893 spin_lock(&qinfo_list_lock);
895 old = find_qinfo(cli, id, cnt);
897 remove_qinfo_hash(old);
898 else if (!old && noquota)
899 insert_qinfo_hash(oqi);
901 spin_unlock(&qinfo_list_lock);
908 CERROR("not enough mem!\n");
917 int osc_quota_cleanup(struct obd_device *obd)
919 struct client_obd *cli = &obd->u.cli;
920 struct osc_quota_info *oqi, *n;
924 spin_lock(&qinfo_list_lock);
925 for (i = 0; i < NR_DQHASH; i++) {
926 list_for_each_entry_safe(oqi, n, &qinfo_hash[i], oqi_hash) {
927 if (oqi->oqi_cli != cli)
929 remove_qinfo_hash(oqi);
933 spin_unlock(&qinfo_list_lock);
938 int osc_quota_init(void)
943 LASSERT(qinfo_cachep == NULL);
944 qinfo_cachep = cfs_mem_cache_create("osc_quota_info",
945 sizeof(struct osc_quota_info),
950 for (i = 0; i < NR_DQHASH; i++)
951 INIT_LIST_HEAD(qinfo_hash + i);
956 int osc_quota_exit(void)
958 struct osc_quota_info *oqi, *n;
962 spin_lock(&qinfo_list_lock);
963 for (i = 0; i < NR_DQHASH; i++) {
964 list_for_each_entry_safe(oqi, n, &qinfo_hash[i], oqi_hash) {
965 remove_qinfo_hash(oqi);
969 spin_unlock(&qinfo_list_lock);
971 rc = cfs_mem_cache_destroy(qinfo_cachep);
972 LASSERTF(rc == 0, "couldn't destory qinfo_cachep slab\n");
979 quota_interface_t mds_quota_interface = {
980 .quota_init = mds_quota_init,
981 .quota_exit = mds_quota_exit,
982 .quota_setup = mds_quota_setup,
983 .quota_cleanup = mds_quota_cleanup,
984 .quota_check = target_quota_check,
985 .quota_ctl = mds_quota_ctl,
986 .quota_fs_cleanup =mds_quota_fs_cleanup,
987 .quota_recovery = mds_quota_recovery,
988 .quota_adjust = mds_quota_adjust,
989 .quota_chkquota = mds_quota_check,
990 .quota_acquire = mds_quota_acquire,
991 .quota_pending_commit = mds_quota_pending_commit,
994 quota_interface_t filter_quota_interface = {
995 .quota_setup = filter_quota_setup,
996 .quota_cleanup = filter_quota_cleanup,
997 .quota_check = target_quota_check,
998 .quota_ctl = filter_quota_ctl,
999 .quota_setinfo = filter_quota_setinfo,
1000 .quota_clearinfo = filter_quota_clearinfo,
1001 .quota_enforce = filter_quota_enforce,
1002 .quota_getflag = filter_quota_getflag,
1003 .quota_acquire = filter_quota_acquire,
1004 .quota_adjust = filter_quota_adjust,
1005 .quota_chkquota = filter_quota_check,
1006 .quota_adjust_qunit = filter_quota_adjust_qunit,
1007 .quota_pending_commit = filter_quota_pending_commit,
1009 #endif /* __KERNEL__ */
1011 quota_interface_t mdc_quota_interface = {
1012 .quota_ctl = client_quota_ctl,
1013 .quota_check = client_quota_check,
1014 .quota_poll_check = client_quota_poll_check,
1017 quota_interface_t osc_quota_interface = {
1018 .quota_ctl = client_quota_ctl,
1019 .quota_check = client_quota_check,
1020 .quota_poll_check = client_quota_poll_check,
1021 .quota_init = osc_quota_init,
1022 .quota_exit = osc_quota_exit,
1023 .quota_chkdq = osc_quota_chkdq,
1024 .quota_setdq = osc_quota_setdq,
1025 .quota_cleanup = osc_quota_cleanup,
1026 .quota_adjust_qunit = client_quota_adjust_qunit,
1029 quota_interface_t lov_quota_interface = {
1030 .quota_check = lov_quota_check,
1031 .quota_ctl = lov_quota_ctl,
1032 .quota_adjust_qunit = lov_quota_adjust_qunit,
1036 static int __init init_lustre_quota(void)
1038 int rc = qunit_cache_init();
1041 PORTAL_SYMBOL_REGISTER(filter_quota_interface);
1042 PORTAL_SYMBOL_REGISTER(mds_quota_interface);
1043 PORTAL_SYMBOL_REGISTER(mdc_quota_interface);
1044 PORTAL_SYMBOL_REGISTER(osc_quota_interface);
1045 PORTAL_SYMBOL_REGISTER(lov_quota_interface);
1049 static void /*__exit*/ exit_lustre_quota(void)
1051 PORTAL_SYMBOL_UNREGISTER(filter_quota_interface);
1052 PORTAL_SYMBOL_UNREGISTER(mds_quota_interface);
1053 PORTAL_SYMBOL_UNREGISTER(mdc_quota_interface);
1054 PORTAL_SYMBOL_UNREGISTER(osc_quota_interface);
1055 PORTAL_SYMBOL_UNREGISTER(lov_quota_interface);
1057 qunit_cache_cleanup();
1060 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
1061 MODULE_DESCRIPTION("Lustre Quota");
1062 MODULE_LICENSE("GPL");
1064 cfs_module(lquota, "1.0.0", init_lustre_quota, exit_lustre_quota);
1066 EXPORT_SYMBOL(mds_quota_interface);
1067 EXPORT_SYMBOL(filter_quota_interface);
1068 EXPORT_SYMBOL(mdc_quota_interface);
1069 EXPORT_SYMBOL(osc_quota_interface);
1070 EXPORT_SYMBOL(lov_quota_interface);
1071 #endif /* __KERNEL */