RETURN(ret);
}
-static inline int lquota_chkdq(quota_interface_t *interface,
- struct client_obd *cli, const unsigned int qid[])
-{
- int rc;
- ENTRY;
-
- QUOTA_CHECK_OP(interface, chkdq);
- rc = QUOTA_OP(interface, chkdq)(cli, qid);
- RETURN(rc);
-}
-
-static inline int lquota_setdq(quota_interface_t *interface,
- struct client_obd *cli, const unsigned int qid[],
- obd_flag valid, obd_flag flags)
-{
- int rc;
- ENTRY;
-
- QUOTA_CHECK_OP(interface, setdq);
- rc = QUOTA_OP(interface, setdq)(cli, qid, valid, flags);
- RETURN(rc);
-}
-
-static inline int lquota_poll_check(quota_interface_t *interface,
- struct obd_export *exp,
- struct if_quotacheck *qchk)
-{
- int rc;
- ENTRY;
-
- QUOTA_CHECK_OP(interface, poll_check);
- rc = QUOTA_OP(interface, poll_check)(exp, qchk);
- RETURN(rc);
-}
-
static inline int lquota_setinfo(quota_interface_t *interface,
struct obd_device *obd,
void *data)
#endif
#ifndef __KERNEL__
-extern quota_interface_t osc_quota_interface;
-extern quota_interface_t lov_quota_interface;
-extern quota_interface_t mdc_quota_interface;
-extern quota_interface_t lmv_quota_interface;
-
#ifndef MAXQUOTAS
#define MAXQUOTAS 2
#endif
return ldlm_namespace_cleanup;
else if (!strcmp(arg, "ldlm_replay_locks"))
return ldlm_replay_locks;
- else if (!strcmp(arg, "mdc_quota_interface"))
- return &mdc_quota_interface;
- else if (!strcmp(arg, "lmv_quota_interface"))
- return &lmv_quota_interface;
- else if (!strcmp(arg, "osc_quota_interface"))
- return &osc_quota_interface;
- else if (!strcmp(arg, "lov_quota_interface"))
- return &lov_quota_interface;
else
return NULL;
}
RETURN(rc);
}
+/**
+ * For lmv, only need to send request to master MDT, and the master MDT will
+ * process with other slave MDTs. The only exception is Q_GETOQUOTA for which
+ * we directly fetch data from the slave MDTs.
+ */
+int lmv_quotactl(struct obd_device *unused, struct obd_export *exp,
+ struct obd_quotactl *oqctl)
+{
+ struct obd_device *obd = class_exp2obd(exp);
+ struct lmv_obd *lmv = &obd->u.lmv;
+ struct lmv_tgt_desc *tgt = &lmv->tgts[0];
+ int rc = 0, i;
+ __u64 curspace, curinodes;
+ ENTRY;
+
+ if (!lmv->desc.ld_tgt_count || !tgt->ltd_active) {
+ CERROR("master lmv inactive\n");
+ RETURN(-EIO);
+ }
+
+ if (oqctl->qc_cmd != Q_GETOQUOTA) {
+ rc = obd_quotactl(tgt->ltd_exp, oqctl);
+ RETURN(rc);
+ }
+
+ curspace = curinodes = 0;
+ for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
+ int err;
+ tgt = &lmv->tgts[i];
+
+ if (tgt->ltd_exp == NULL)
+ continue;
+ if (!tgt->ltd_active) {
+ CDEBUG(D_HA, "mdt %d is inactive.\n", i);
+ continue;
+ }
+
+ err = obd_quotactl(tgt->ltd_exp, oqctl);
+ if (err) {
+ CERROR("getquota on mdt %d failed. %d\n", i, err);
+ if (!rc)
+ rc = err;
+ } else {
+ curspace += oqctl->qc_dqblk.dqb_curspace;
+ curinodes += oqctl->qc_dqblk.dqb_curinodes;
+ }
+ }
+ oqctl->qc_dqblk.dqb_curspace = curspace;
+ oqctl->qc_dqblk.dqb_curinodes = curinodes;
+
+ RETURN(rc);
+}
+
+int lmv_quotacheck(struct obd_device *unused, struct obd_export *exp,
+ struct obd_quotactl *oqctl)
+{
+ struct obd_device *obd = class_exp2obd(exp);
+ struct lmv_obd *lmv = &obd->u.lmv;
+ struct lmv_tgt_desc *tgt;
+ int i, rc = 0;
+ ENTRY;
+
+ for (i = 0, tgt = lmv->tgts; i < lmv->desc.ld_tgt_count; i++, tgt++) {
+ int err;
+
+ if (!tgt->ltd_active) {
+ CERROR("lmv idx %d inactive\n", i);
+ RETURN(-EIO);
+ }
+
+ err = obd_quotacheck(tgt->ltd_exp, oqctl);
+ if (err && !rc)
+ rc = err;
+ }
+
+ RETURN(rc);
+}
struct obd_ops lmv_obd_ops = {
.o_owner = THIS_MODULE,
.o_notify = lmv_notify,
.o_get_uuid = lmv_get_uuid,
.o_iocontrol = lmv_iocontrol,
- .o_fid_delete = lmv_fid_delete
+ .o_fid_delete = lmv_fid_delete,
+ .o_quotacheck = lmv_quotacheck,
+ .o_quotactl = lmv_quotactl
};
struct md_ops lmv_md_ops = {
.m_revalidate_lock = lmv_revalidate_lock
};
-static quota_interface_t *quota_interface;
-extern quota_interface_t lmv_quota_interface;
-
int __init lmv_init(void)
{
struct lprocfs_static_vars lvars;
lprocfs_lmv_init_vars(&lvars);
- cfs_request_module("lquota");
- quota_interface = PORTAL_SYMBOL_GET(lmv_quota_interface);
- init_obd_quota_ops(quota_interface, &lmv_obd_ops);
-
rc = class_register_type(&lmv_obd_ops, &lmv_md_ops,
lvars.module_vars, LUSTRE_LMV_NAME, NULL);
- if (rc) {
- if (quota_interface)
- PORTAL_SYMBOL_PUT(lmv_quota_interface);
+ if (rc)
cfs_mem_cache_destroy(lmv_object_cache);
- }
return rc;
}
#ifdef __KERNEL__
static void lmv_exit(void)
{
- if (quota_interface)
- PORTAL_SYMBOL_PUT(lmv_quota_interface);
-
class_unregister_type(LUSTRE_LMV_NAME);
LASSERTF(cfs_atomic_read(&lmv_object_count) == 0,
}
EXPORT_SYMBOL(lov_stripe_unlock);
+static int lov_quotactl(struct obd_device *obd, struct obd_export *exp,
+ struct obd_quotactl *oqctl)
+{
+ struct lov_obd *lov = &obd->u.lov;
+ struct lov_tgt_desc *tgt;
+ __u64 curspace = 0;
+ __u64 bhardlimit = 0;
+ int i, rc = 0;
+ ENTRY;
+
+ if (oqctl->qc_cmd != LUSTRE_Q_QUOTAON &&
+ oqctl->qc_cmd != LUSTRE_Q_QUOTAOFF &&
+ oqctl->qc_cmd != Q_GETOQUOTA &&
+ oqctl->qc_cmd != Q_INITQUOTA &&
+ oqctl->qc_cmd != LUSTRE_Q_SETQUOTA &&
+ oqctl->qc_cmd != Q_FINVALIDATE) {
+ CERROR("bad quota opc %x for lov obd", oqctl->qc_cmd);
+ RETURN(-EFAULT);
+ }
+
+ /* for lov tgt */
+ obd_getref(obd);
+ for (i = 0; i < lov->desc.ld_tgt_count; i++) {
+ int err;
+
+ tgt = lov->lov_tgts[i];
+
+ if (!tgt)
+ continue;
+
+ if (!tgt->ltd_active || tgt->ltd_reap) {
+ if (oqctl->qc_cmd == Q_GETOQUOTA &&
+ lov->lov_tgts[i]->ltd_activate) {
+ rc = -EREMOTEIO;
+ CERROR("ost %d is inactive\n", i);
+ } else {
+ CDEBUG(D_HA, "ost %d is inactive\n", i);
+ }
+ continue;
+ }
+
+ err = obd_quotactl(tgt->ltd_exp, oqctl);
+ if (err) {
+ if (tgt->ltd_active && !rc)
+ rc = err;
+ continue;
+ }
+
+ if (oqctl->qc_cmd == Q_GETOQUOTA) {
+ curspace += oqctl->qc_dqblk.dqb_curspace;
+ bhardlimit += oqctl->qc_dqblk.dqb_bhardlimit;
+ }
+ }
+ obd_putref(obd);
+
+ if (oqctl->qc_cmd == Q_GETOQUOTA) {
+ oqctl->qc_dqblk.dqb_curspace = curspace;
+ oqctl->qc_dqblk.dqb_bhardlimit = bhardlimit;
+ }
+ RETURN(rc);
+}
+
+static int lov_quotacheck(struct obd_device *obd, struct obd_export *exp,
+ struct obd_quotactl *oqctl)
+{
+ struct lov_obd *lov = &obd->u.lov;
+ int i, rc = 0;
+ ENTRY;
+
+ obd_getref(obd);
+
+ for (i = 0; i < lov->desc.ld_tgt_count; i++) {
+ if (!lov->lov_tgts[i])
+ continue;
+
+ /* Skip quota check on the administratively disabled OSTs. */
+ if (!lov->lov_tgts[i]->ltd_activate) {
+ CWARN("lov idx %d was administratively disabled, "
+ "skip quotacheck on it.\n", i);
+ continue;
+ }
+
+ if (!lov->lov_tgts[i]->ltd_active) {
+ CERROR("lov idx %d inactive\n", i);
+ rc = -EIO;
+ goto out;
+ }
+ }
+
+ for (i = 0; i < lov->desc.ld_tgt_count; i++) {
+ int err;
+
+ if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_activate)
+ continue;
+
+ err = obd_quotacheck(lov->lov_tgts[i]->ltd_exp, oqctl);
+ if (err && !rc)
+ rc = err;
+ }
+
+out:
+ obd_putref(obd);
+
+ RETURN(rc);
+}
+
+int lov_quota_adjust_qunit(struct obd_export *exp,
+ struct quota_adjust_qunit *oqaq,
+ struct lustre_quota_ctxt *qctxt,
+ struct ptlrpc_request_set *rqset)
+{
+ struct obd_device *obd = class_exp2obd(exp);
+ struct lov_obd *lov = &obd->u.lov;
+ int i, err, rc = 0;
+ unsigned no_set = 0;
+ ENTRY;
+
+ if (!QAQ_IS_ADJBLK(oqaq)) {
+ CERROR("bad qaq_flags %x for lov obd.\n", oqaq->qaq_flags);
+ RETURN(-EFAULT);
+ }
+
+ if (rqset == NULL) {
+ rqset = ptlrpc_prep_set();
+ if (!rqset)
+ RETURN(-ENOMEM);
+ no_set = 1;
+ }
+
+ obd_getref(obd);
+ for (i = 0; i < lov->desc.ld_tgt_count; i++) {
+
+ if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_active) {
+ CDEBUG(D_HA, "ost %d is inactive\n", i);
+ continue;
+ }
+
+ err = obd_quota_adjust_qunit(lov->lov_tgts[i]->ltd_exp, oqaq,
+ NULL, rqset);
+ if (err) {
+ if (lov->lov_tgts[i]->ltd_active && !rc)
+ rc = err;
+ continue;
+ }
+ }
+
+ err = ptlrpc_set_wait(rqset);
+ if (!rc)
+ rc = err;
+
+ /* Destroy the set if none was provided by the caller */
+ if (no_set)
+ ptlrpc_set_destroy(rqset);
+
+ obd_putref(obd);
+ RETURN(rc);
+}
struct obd_ops lov_obd_ops = {
.o_owner = THIS_MODULE,
.o_pool_del = lov_pool_del,
.o_getref = lov_getref,
.o_putref = lov_putref,
+ .o_quotactl = lov_quotactl,
+ .o_quotacheck = lov_quotacheck,
+ .o_quota_adjust_qunit = lov_quota_adjust_qunit,
};
static quota_interface_t *quota_interface;
renew_capa_cb_t ra_cb;
};
-static quota_interface_t *quota_interface;
-extern quota_interface_t mdc_quota_interface;
-
static int mdc_cleanup(struct obd_device *obd);
int mdc_unpack_capa(struct obd_export *exp, struct ptlrpc_request *req,
static int mdc_ioc_hsm_ct_start(struct obd_export *exp,
struct lustre_kernelcomm *lk);
+static int mdc_quotacheck(struct obd_device *unused, struct obd_export *exp,
+ struct obd_quotactl *oqctl)
+{
+ struct client_obd *cli = &exp->exp_obd->u.cli;
+ struct ptlrpc_request *req;
+ struct obd_quotactl *body;
+ int rc;
+ ENTRY;
+
+ req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
+ &RQF_MDS_QUOTACHECK, LUSTRE_MDS_VERSION,
+ MDS_QUOTACHECK);
+ if (req == NULL)
+ RETURN(-ENOMEM);
+
+ body = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
+ *body = *oqctl;
+
+ ptlrpc_request_set_replen(req);
+
+ /* the next poll will find -ENODATA, that means quotacheck is
+ * going on */
+ cli->cl_qchk_stat = -ENODATA;
+ rc = ptlrpc_queue_wait(req);
+ if (rc)
+ cli->cl_qchk_stat = rc;
+ ptlrpc_req_finished(req);
+ RETURN(rc);
+}
+
+static int mdc_quota_poll_check(struct obd_export *exp,
+ struct if_quotacheck *qchk)
+{
+ struct client_obd *cli = &exp->exp_obd->u.cli;
+ int rc;
+ ENTRY;
+
+ qchk->obd_uuid = cli->cl_target_uuid;
+ memcpy(qchk->obd_type, LUSTRE_MDS_NAME, strlen(LUSTRE_MDS_NAME));
+
+ rc = cli->cl_qchk_stat;
+ /* the client is not the previous one */
+ if (rc == CL_NOT_QUOTACHECKED)
+ rc = -EINTR;
+ RETURN(rc);
+}
+
+static int mdc_quotactl(struct obd_device *unused, struct obd_export *exp,
+ struct obd_quotactl *oqctl)
+{
+ struct ptlrpc_request *req;
+ struct obd_quotactl *oqc;
+ int rc;
+ ENTRY;
+
+ req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
+ &RQF_MDS_QUOTACTL, LUSTRE_MDS_VERSION,
+ MDS_QUOTACTL);
+ if (req == NULL)
+ RETURN(-ENOMEM);
+
+ oqc = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
+ *oqc = *oqctl;
+
+ ptlrpc_request_set_replen(req);
+ ptlrpc_at_set_req_timeout(req);
+ req->rq_no_resend = 1;
+
+ rc = ptlrpc_queue_wait(req);
+ if (rc)
+ CERROR("ptlrpc_queue_wait failed, rc: %d\n", rc);
+
+ if (req->rq_repmsg &&
+ (oqc = req_capsule_server_get(&req->rq_pill, &RMF_OBD_QUOTACTL))) {
+ *oqctl = *oqc;
+ } else if (!rc) {
+ CERROR ("Can't unpack obd_quotactl\n");
+ rc = -EPROTO;
+ }
+ ptlrpc_req_finished(req);
+
+ RETURN(rc);
+}
+
static int mdc_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
void *karg, void *uarg)
{
}
#endif
case OBD_IOC_POLL_QUOTACHECK:
- rc = lquota_poll_check(quota_interface, exp,
- (struct if_quotacheck *)karg);
+ rc = mdc_quota_poll_check(exp, (struct if_quotacheck *)karg);
GOTO(out, rc);
case OBD_IOC_PING_TARGET:
rc = ptlrpc_obd_ping(obd);
.o_get_info = mdc_get_info,
.o_process_config = mdc_process_config,
.o_get_uuid = mdc_get_uuid,
+ .o_quotactl = mdc_quotactl,
+ .o_quotacheck = mdc_quotacheck
};
struct md_ops mdc_md_ops = {
struct lprocfs_static_vars lvars = { 0 };
lprocfs_mdc_init_vars(&lvars);
- cfs_request_module("lquota");
- quota_interface = PORTAL_SYMBOL_GET(mdc_quota_interface);
- init_obd_quota_ops(quota_interface, &mdc_obd_ops);
-
rc = class_register_type(&mdc_obd_ops, &mdc_md_ops, lvars.module_vars,
LUSTRE_MDC_NAME, NULL);
- if (rc && quota_interface)
- PORTAL_SYMBOL_PUT(mdc_quota_interface);
-
RETURN(rc);
}
#ifdef __KERNEL__
static void /*__exit*/ mdc_exit(void)
{
- if (quota_interface)
- PORTAL_SYMBOL_PUT(mdc_quota_interface);
-
class_unregister_type(LUSTRE_MDC_NAME);
}
MODULES := osc
-osc-objs := osc_request.o lproc_osc.o osc_create.o osc_dev.o osc_object.o osc_page.o osc_lock.o osc_io.o
+osc-objs := osc_request.o lproc_osc.o osc_create.o osc_dev.o osc_object.o osc_page.o osc_lock.o osc_io.o osc_quota.o
EXTRA_DIST = $(osc-objs:%.o=%.c) osc_internal.h osc_cl_internal.h
if LIBLUSTRE
noinst_LIBRARIES = libosc.a
-libosc_a_SOURCES = osc_request.c osc_create.c osc_internal.h osc_cl_internal.h osc_dev.c osc_object.c osc_page.c osc_lock.c osc_io.c
+libosc_a_SOURCES = osc_request.c osc_create.c osc_internal.h osc_cl_internal.h osc_dev.c osc_object.c osc_page.c osc_lock.c osc_io.c osc_quota.c
libosc_a_CPPFLAGS = $(LLCPPFLAGS)
libosc_a_CFLAGS = $(LLCFLAGS)
osc_page.c \
osc_lock.c \
osc_io.c \
- osc_request.c
+ osc_request.c \
+ osc_quota.c
osc_CFLAGS := $(EXTRA_KCFLAGS)
osc_LDFLAGS := $(EXTRA_KLDFLAGS)
int osc_dlm_lock_pageref(struct ldlm_lock *dlm);
+int osc_quota_init(void);
+int osc_quota_exit(void);
+int osc_quota_cleanup(struct obd_device *obd);
+int osc_quota_setdq(struct client_obd *cli, const unsigned int qid[],
+ obd_flag valid, obd_flag flags);
+int osc_quota_chkdq(struct client_obd *cli, const unsigned int qid[]);
+int osc_quotactl(struct obd_device *unused, struct obd_export *exp,
+ struct obd_quotactl *oqctl);
+int osc_quotacheck(struct obd_device *unused, struct obd_export *exp,
+ struct obd_quotactl *oqctl);
+int osc_quota_poll_check(struct obd_export *exp, struct if_quotacheck *qchk);
+int osc_quota_adjust_qunit(struct obd_export *exp,
+ struct quota_adjust_qunit *oqaq,
+ struct lustre_quota_ctxt *qctxt,
+ struct ptlrpc_request_set *rqset);
#endif /* OSC_INTERNAL_H */
--- /dev/null
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * GPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA
+ *
+ * GPL HEADER END
+ */
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 Whamcloud, Inc.
+ *
+ * Code originally extracted from quota directory
+ */
+#ifndef __KERNEL__
+# include <liblustre.h>
+#endif
+
+#include <obd_ost.h>
+#include "osc_internal.h"
+
+struct osc_quota_info {
+ cfs_list_t oqi_hash; /* hash list */
+ struct client_obd *oqi_cli; /* osc obd */
+ unsigned int oqi_id; /* uid/gid of a file */
+ short oqi_type; /* quota type */
+};
+
+cfs_spinlock_t qinfo_list_lock = CFS_SPIN_LOCK_UNLOCKED;
+
+static cfs_list_t qinfo_hash[NR_DQHASH];
+/* SLAB cache for client quota context */
+cfs_mem_cache_t *qinfo_cachep = NULL;
+
+static inline int hashfn(struct client_obd *cli, unsigned long id, int type)
+ __attribute__((__const__));
+
+static inline int hashfn(struct client_obd *cli, unsigned long id, int type)
+{
+ unsigned long tmp = ((unsigned long)cli>>6) ^ id;
+ tmp = (tmp * (MAXQUOTAS - type)) % NR_DQHASH;
+ return tmp;
+}
+
+/* caller must hold qinfo_list_lock */
+static inline void insert_qinfo_hash(struct osc_quota_info *oqi)
+{
+ cfs_list_t *head = qinfo_hash +
+ hashfn(oqi->oqi_cli, oqi->oqi_id, oqi->oqi_type);
+
+ LASSERT_SPIN_LOCKED(&qinfo_list_lock);
+ cfs_list_add(&oqi->oqi_hash, head);
+}
+
+/* caller must hold qinfo_list_lock */
+static inline void remove_qinfo_hash(struct osc_quota_info *oqi)
+{
+ LASSERT_SPIN_LOCKED(&qinfo_list_lock);
+ cfs_list_del_init(&oqi->oqi_hash);
+}
+
+/* caller must hold qinfo_list_lock */
+static inline struct osc_quota_info *find_qinfo(struct client_obd *cli,
+ unsigned int id, int type)
+{
+ struct osc_quota_info *oqi;
+ unsigned int hashent = hashfn(cli, id, type);
+ ENTRY;
+
+ LASSERT_SPIN_LOCKED(&qinfo_list_lock);
+ cfs_list_for_each_entry(oqi, &qinfo_hash[hashent], oqi_hash) {
+ if (oqi->oqi_cli == cli &&
+ oqi->oqi_id == id && oqi->oqi_type == type)
+ RETURN(oqi);
+ }
+ RETURN(NULL);
+}
+
+static struct osc_quota_info *alloc_qinfo(struct client_obd *cli,
+ unsigned int id, int type)
+{
+ struct osc_quota_info *oqi;
+ ENTRY;
+
+ OBD_SLAB_ALLOC(oqi, qinfo_cachep, CFS_ALLOC_IO, sizeof(*oqi));
+ if(!oqi)
+ RETURN(NULL);
+
+ CFS_INIT_LIST_HEAD(&oqi->oqi_hash);
+ oqi->oqi_cli = cli;
+ oqi->oqi_id = id;
+ oqi->oqi_type = type;
+
+ RETURN(oqi);
+}
+
+static void free_qinfo(struct osc_quota_info *oqi)
+{
+ OBD_SLAB_FREE(oqi, qinfo_cachep, sizeof(*oqi));
+}
+
+int osc_quota_chkdq(struct client_obd *cli, const unsigned int qid[])
+{
+ unsigned int id;
+ int cnt, rc = QUOTA_OK;
+ ENTRY;
+
+ cfs_spin_lock(&qinfo_list_lock);
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+ struct osc_quota_info *oqi = NULL;
+
+ id = (cnt == USRQUOTA) ? qid[USRQUOTA] : qid[GRPQUOTA];
+ oqi = find_qinfo(cli, id, cnt);
+ if (oqi) {
+ rc = NO_QUOTA;
+ break;
+ }
+ }
+ cfs_spin_unlock(&qinfo_list_lock);
+
+ if (rc == NO_QUOTA)
+ CDEBUG(D_QUOTA, "chkdq found noquota for %s %d\n",
+ cnt == USRQUOTA ? "user" : "group", id);
+ RETURN(rc);
+}
+
+int osc_quota_setdq(struct client_obd *cli, const unsigned int qid[],
+ obd_flag valid, obd_flag flags)
+{
+ unsigned int id;
+ obd_flag noquota;
+ int cnt, rc = 0;
+ ENTRY;
+
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+ struct osc_quota_info *oqi = NULL, *old;
+
+ if (!(valid & ((cnt == USRQUOTA) ?
+ OBD_MD_FLUSRQUOTA : OBD_MD_FLGRPQUOTA)))
+ continue;
+
+ id = (cnt == USRQUOTA) ? qid[USRQUOTA] : qid[GRPQUOTA];
+ noquota = (cnt == USRQUOTA) ?
+ (flags & OBD_FL_NO_USRQUOTA) : (flags & OBD_FL_NO_GRPQUOTA);
+
+ if (noquota) {
+ oqi = alloc_qinfo(cli, id, cnt);
+ if (!oqi) {
+ rc = -ENOMEM;
+ CDEBUG(D_QUOTA, "setdq for %s %d failed, "
+ "(rc = %d)\n",
+ cnt == USRQUOTA ? "user" : "group",
+ id, rc);
+ break;
+ }
+ }
+
+ cfs_spin_lock(&qinfo_list_lock);
+ old = find_qinfo(cli, id, cnt);
+ if (old && !noquota)
+ remove_qinfo_hash(old);
+ else if (!old && noquota)
+ insert_qinfo_hash(oqi);
+ cfs_spin_unlock(&qinfo_list_lock);
+
+ if (old && !noquota)
+ CDEBUG(D_QUOTA, "setdq to remove for %s %d\n",
+ cnt == USRQUOTA ? "user" : "group", id);
+ else if (!old && noquota)
+ CDEBUG(D_QUOTA, "setdq to insert for %s %d\n",
+ cnt == USRQUOTA ? "user" : "group", id);
+
+ if (old) {
+ if (noquota)
+ free_qinfo(oqi);
+ else
+ free_qinfo(old);
+ }
+ }
+ RETURN(rc);
+}
+
+int osc_quota_cleanup(struct obd_device *obd)
+{
+ struct client_obd *cli = &obd->u.cli;
+ struct osc_quota_info *oqi, *n;
+ int i;
+ ENTRY;
+
+ cfs_spin_lock(&qinfo_list_lock);
+ for (i = 0; i < NR_DQHASH; i++) {
+ cfs_list_for_each_entry_safe(oqi, n, &qinfo_hash[i], oqi_hash) {
+ if (oqi->oqi_cli != cli)
+ continue;
+ remove_qinfo_hash(oqi);
+ free_qinfo(oqi);
+ }
+ }
+ cfs_spin_unlock(&qinfo_list_lock);
+
+ RETURN(0);
+}
+
+int osc_quota_init()
+{
+ int i;
+ ENTRY;
+
+ LASSERT(qinfo_cachep == NULL);
+ qinfo_cachep = cfs_mem_cache_create("osc_quota_info",
+ sizeof(struct osc_quota_info),
+ 0, 0);
+ if (!qinfo_cachep)
+ RETURN(-ENOMEM);
+
+ for (i = 0; i < NR_DQHASH; i++)
+ CFS_INIT_LIST_HEAD(qinfo_hash + i);
+
+ RETURN(0);
+}
+
+int osc_quota_exit()
+{
+ struct osc_quota_info *oqi, *n;
+ int i, rc;
+ ENTRY;
+
+ cfs_spin_lock(&qinfo_list_lock);
+ for (i = 0; i < NR_DQHASH; i++) {
+ cfs_list_for_each_entry_safe(oqi, n, &qinfo_hash[i], oqi_hash) {
+ remove_qinfo_hash(oqi);
+ free_qinfo(oqi);
+ }
+ }
+ cfs_spin_unlock(&qinfo_list_lock);
+
+ rc = cfs_mem_cache_destroy(qinfo_cachep);
+ LASSERTF(rc == 0, "couldn't destory qinfo_cachep slab\n");
+ qinfo_cachep = NULL;
+
+ RETURN(0);
+}
+
+int osc_quotactl(struct obd_device *unused, struct obd_export *exp,
+ struct obd_quotactl *oqctl)
+{
+ struct ptlrpc_request *req;
+ struct obd_quotactl *oqc;
+ int rc;
+ ENTRY;
+
+ req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
+ &RQF_OST_QUOTACTL, LUSTRE_OST_VERSION,
+ OST_QUOTACTL);
+ if (req == NULL)
+ RETURN(-ENOMEM);
+
+ oqc = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
+ *oqc = *oqctl;
+
+ ptlrpc_request_set_replen(req);
+ ptlrpc_at_set_req_timeout(req);
+ req->rq_no_resend = 1;
+
+ rc = ptlrpc_queue_wait(req);
+ if (rc)
+ CERROR("ptlrpc_queue_wait failed, rc: %d\n", rc);
+
+ if (req->rq_repmsg &&
+ (oqc = req_capsule_server_get(&req->rq_pill, &RMF_OBD_QUOTACTL))) {
+ *oqctl = *oqc;
+ } else if (!rc) {
+ CERROR ("Can't unpack obd_quotactl\n");
+ rc = -EPROTO;
+ }
+ ptlrpc_req_finished(req);
+
+ RETURN(rc);
+}
+
+int osc_quotacheck(struct obd_device *unused, struct obd_export *exp,
+ struct obd_quotactl *oqctl)
+{
+ struct client_obd *cli = &exp->exp_obd->u.cli;
+ struct ptlrpc_request *req;
+ struct obd_quotactl *body;
+ int rc;
+ ENTRY;
+
+ req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
+ &RQF_OST_QUOTACHECK, LUSTRE_OST_VERSION,
+ OST_QUOTACHECK);
+ if (req == NULL)
+ RETURN(-ENOMEM);
+
+ body = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
+ *body = *oqctl;
+
+ ptlrpc_request_set_replen(req);
+
+ /* the next poll will find -ENODATA, that means quotacheck is
+ * going on */
+ cli->cl_qchk_stat = -ENODATA;
+ rc = ptlrpc_queue_wait(req);
+ if (rc)
+ cli->cl_qchk_stat = rc;
+ ptlrpc_req_finished(req);
+ RETURN(rc);
+}
+
+int osc_quota_poll_check(struct obd_export *exp, struct if_quotacheck *qchk)
+{
+ struct client_obd *cli = &exp->exp_obd->u.cli;
+ int rc;
+ ENTRY;
+
+ qchk->obd_uuid = cli->cl_target_uuid;
+ memcpy(qchk->obd_type, LUSTRE_OST_NAME, strlen(LUSTRE_OST_NAME));
+
+ rc = cli->cl_qchk_stat;
+ /* the client is not the previous one */
+ if (rc == CL_NOT_QUOTACHECKED)
+ rc = -EINTR;
+ RETURN(rc);
+}
+
+int osc_quota_adjust_qunit(struct obd_export *exp,
+ struct quota_adjust_qunit *oqaq,
+ struct lustre_quota_ctxt *qctxt,
+ struct ptlrpc_request_set *rqset)
+{
+ struct ptlrpc_request *req;
+ struct quota_adjust_qunit *oqa;
+ int rc = 0;
+ ENTRY;
+
+ /* client don't support this kind of operation, abort it */
+ if (!(exp->exp_connect_flags & OBD_CONNECT_CHANGE_QS)) {
+ CDEBUG(D_QUOTA, "osc: %s don't support change qunit size\n",
+ exp->exp_obd->obd_name);
+ RETURN(rc);
+ }
+ if (strcmp(exp->exp_obd->obd_type->typ_name, LUSTRE_OSC_NAME))
+ RETURN(-EINVAL);
+
+ LASSERT(rqset);
+
+ req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
+ &RQF_OST_QUOTA_ADJUST_QUNIT,
+ LUSTRE_OST_VERSION,
+ OST_QUOTA_ADJUST_QUNIT);
+ if (req == NULL)
+ RETURN(-ENOMEM);
+
+ oqa = req_capsule_client_get(&req->rq_pill, &RMF_QUOTA_ADJUST_QUNIT);
+ *oqa = *oqaq;
+
+ ptlrpc_request_set_replen(req);
+
+ ptlrpc_set_add_req(rqset, req);
+ RETURN(rc);
+}
#include <lustre_param.h>
#include "osc_internal.h"
-static quota_interface_t *quota_interface = NULL;
-extern quota_interface_t osc_quota_interface;
-
static void osc_release_ppga(struct brw_page **ppga, obd_count count);
static int brw_interpret(const struct lu_env *env,
struct ptlrpc_request *req, void *data, int rc);
RETURN(-EPROTO);
}
-#ifdef HAVE_QUOTA_SUPPORT
/* set/clear over quota flag for a uid/gid */
if (lustre_msg_get_opc(req->rq_reqmsg) == OST_WRITE &&
body->oa.o_valid & (OBD_MD_FLUSRQUOTA | OBD_MD_FLGRPQUOTA)) {
CDEBUG(D_QUOTA, "setdq for [%u %u] with valid "LPX64", flags %x\n",
body->oa.o_uid, body->oa.o_gid, body->oa.o_valid,
body->oa.o_flags);
- lquota_setdq(quota_interface, cli, qid, body->oa.o_valid,
- body->oa.o_flags);
+ osc_quota_setdq(cli, qid, body->oa.o_valid, body->oa.o_flags);
}
-#endif
osc_update_grant(cli, body);
qid[USRQUOTA] = attr.cat_uid;
qid[GRPQUOTA] = attr.cat_gid;
if (rc == 0 &&
- lquota_chkdq(quota_interface, cli, qid) == NO_QUOTA)
+ osc_quota_chkdq(cli, qid) == NO_QUOTA)
rc = -EDQUOT;
if (rc)
RETURN(rc);
data->ioc_offset);
GOTO(out, err);
case OBD_IOC_POLL_QUOTACHECK:
- err = lquota_poll_check(quota_interface, exp,
- (struct if_quotacheck *)karg);
+ err = osc_quota_poll_check(exp, (struct if_quotacheck *)karg);
GOTO(out, err);
case OBD_IOC_PING_TARGET:
err = ptlrpc_obd_ping(obd);
ENTRY;
/* free memory of osc quota cache */
- lquota_cleanup(quota_interface, obd);
+ osc_quota_cleanup(obd);
rc = client_obd_cleanup(obd);
.o_llog_init = osc_llog_init,
.o_llog_finish = osc_llog_finish,
.o_process_config = osc_process_config,
+ .o_quotactl = osc_quotactl,
+ .o_quotacheck = osc_quotacheck,
+ .o_quota_adjust_qunit = osc_quota_adjust_qunit,
};
extern struct lu_kmem_descr osc_caches[];
lprocfs_osc_init_vars(&lvars);
- cfs_request_module("lquota");
- quota_interface = PORTAL_SYMBOL_GET(osc_quota_interface);
- lquota_init(quota_interface);
- init_obd_quota_ops(quota_interface, &osc_obd_ops);
-
+ osc_quota_init();
rc = class_register_type(&osc_obd_ops, NULL, lvars.module_vars,
LUSTRE_OSC_NAME, &osc_device_type);
if (rc) {
- if (quota_interface)
- PORTAL_SYMBOL_PUT(osc_quota_interface);
lu_kmem_fini(osc_caches);
RETURN(rc);
}
{
lu_device_type_fini(&osc_device_type);
- lquota_exit(quota_interface);
- if (quota_interface)
- PORTAL_SYMBOL_PUT(osc_quota_interface);
-
+ osc_quota_exit();
class_unregister_type(LUSTRE_OSC_NAME);
lu_kmem_fini(osc_caches);
}
}
#endif /* __KERNEL__ */
#endif
-
-int client_quota_adjust_qunit(struct obd_export *exp,
- struct quota_adjust_qunit *oqaq,
- struct lustre_quota_ctxt *qctxt,
- struct ptlrpc_request_set *rqset)
-{
- struct ptlrpc_request *req;
- struct quota_adjust_qunit *oqa;
- int rc = 0;
- ENTRY;
-
- /* client don't support this kind of operation, abort it */
- if (!(exp->exp_connect_flags & OBD_CONNECT_CHANGE_QS)) {
- CDEBUG(D_QUOTA, "osc: %s don't support change qunit size\n",
- exp->exp_obd->obd_name);
- RETURN(rc);
- }
- if (strcmp(exp->exp_obd->obd_type->typ_name, LUSTRE_OSC_NAME))
- RETURN(-EINVAL);
-
- LASSERT(rqset);
-
- req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
- &RQF_OST_QUOTA_ADJUST_QUNIT,
- LUSTRE_OST_VERSION,
- OST_QUOTA_ADJUST_QUNIT);
- if (req == NULL)
- RETURN(-ENOMEM);
-
- oqa = req_capsule_client_get(&req->rq_pill, &RMF_QUOTA_ADJUST_QUNIT);
- *oqa = *oqaq;
-
- ptlrpc_request_set_replen(req);
-
- ptlrpc_set_add_req(rqset, req);
- RETURN (rc);
-}
-
-int lov_quota_adjust_qunit(struct obd_export *exp,
- struct quota_adjust_qunit *oqaq,
- struct lustre_quota_ctxt *qctxt,
- struct ptlrpc_request_set *rqset)
-{
- struct obd_device *obd = class_exp2obd(exp);
- struct lov_obd *lov = &obd->u.lov;
- int i, err, rc = 0;
- unsigned no_set = 0;
- ENTRY;
-
- if (!QAQ_IS_ADJBLK(oqaq)) {
- CERROR("bad qaq_flags %x for lov obd.\n", oqaq->qaq_flags);
- RETURN(-EFAULT);
- }
-
-
- if (rqset == NULL) {
- rqset = ptlrpc_prep_set();
- if (!rqset)
- RETURN(-ENOMEM);
- no_set = 1;
- }
-
- obd_getref(obd);
- for (i = 0; i < lov->desc.ld_tgt_count; i++) {
-
- if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_active) {
- CDEBUG(D_HA, "ost %d is inactive\n", i);
- continue;
- }
-
- err = obd_quota_adjust_qunit(lov->lov_tgts[i]->ltd_exp, oqaq,
- NULL, rqset);
- if (err) {
- if (lov->lov_tgts[i]->ltd_active && !rc)
- rc = err;
- continue;
- }
- }
-
- err = ptlrpc_set_wait(rqset);
- if (!rc)
- rc = err;
-
- /* Destroy the set if none was provided by the caller */
- if (no_set)
- ptlrpc_set_destroy(rqset);
-
- obd_putref(obd);
- RETURN(rc);
-}
#endif /* __KERNEL__ */
#endif /* HAVE_QUOTA_SUPPORT */
-
-int client_quota_check(struct obd_device *unused, struct obd_export *exp,
- struct obd_quotactl *oqctl)
-{
- struct client_obd *cli = &exp->exp_obd->u.cli;
- struct ptlrpc_request *req;
- struct obd_quotactl *body;
- const struct req_format *rf;
- int ver, opc, rc;
- ENTRY;
-
- if (!strcmp(exp->exp_obd->obd_type->typ_name, LUSTRE_MDC_NAME)) {
- rf = &RQF_MDS_QUOTACHECK;
- ver = LUSTRE_MDS_VERSION;
- opc = MDS_QUOTACHECK;
- } else if (!strcmp(exp->exp_obd->obd_type->typ_name, LUSTRE_OSC_NAME)) {
- rf = &RQF_OST_QUOTACHECK;
- ver = LUSTRE_OST_VERSION;
- opc = OST_QUOTACHECK;
- } else {
- RETURN(-EINVAL);
- }
-
- req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp), rf, ver, opc);
- if (req == NULL)
- RETURN(-ENOMEM);
-
- body = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
- *body = *oqctl;
-
- ptlrpc_request_set_replen(req);
-
- /* the next poll will find -ENODATA, that means quotacheck is
- * going on */
- cli->cl_qchk_stat = -ENODATA;
- rc = ptlrpc_queue_wait(req);
- if (rc)
- cli->cl_qchk_stat = rc;
- ptlrpc_req_finished(req);
- RETURN(rc);
-}
-
-int client_quota_poll_check(struct obd_export *exp, struct if_quotacheck *qchk)
-{
- struct client_obd *cli = &exp->exp_obd->u.cli;
- int rc;
- ENTRY;
-
- rc = cli->cl_qchk_stat;
-
- /* the client is not the previous one */
- if (rc == CL_NOT_QUOTACHECKED)
- rc = -EINTR;
-
- qchk->obd_uuid = cli->cl_target_uuid;
- /* FIXME change strncmp to strcmp and save the strlen op */
- if (strncmp(exp->exp_obd->obd_type->typ_name, LUSTRE_OSC_NAME,
- strlen(LUSTRE_OSC_NAME)) == 0)
- memcpy(qchk->obd_type, LUSTRE_OST_NAME,
- strlen(LUSTRE_OST_NAME));
- else if (strncmp(exp->exp_obd->obd_type->typ_name, LUSTRE_MDC_NAME,
- strlen(LUSTRE_MDC_NAME)) == 0)
- memcpy(qchk->obd_type, LUSTRE_MDS_NAME,
- strlen(LUSTRE_MDS_NAME));
-
- RETURN(rc);
-}
-
-int lmv_quota_check(struct obd_device *unused, struct obd_export *exp,
- struct obd_quotactl *oqctl)
-{
- struct obd_device *obd = class_exp2obd(exp);
- struct lmv_obd *lmv = &obd->u.lmv;
- struct lmv_tgt_desc *tgt;
- int i, rc = 0;
- ENTRY;
-
- for (i = 0, tgt = lmv->tgts; i < lmv->desc.ld_tgt_count; i++, tgt++) {
- int err;
-
- if (!tgt->ltd_active) {
- CERROR("lmv idx %d inactive\n", i);
- RETURN(-EIO);
- }
-
- err = obd_quotacheck(tgt->ltd_exp, oqctl);
- if (err && !rc)
- rc = err;
- }
-
- RETURN(rc);
-}
-
-int lov_quota_check(struct obd_device *unused, struct obd_export *exp,
- struct obd_quotactl *oqctl)
-{
- struct obd_device *obd = class_exp2obd(exp);
- struct lov_obd *lov = &obd->u.lov;
- int i, rc = 0;
- ENTRY;
-
- obd_getref(obd);
-
- for (i = 0; i < lov->desc.ld_tgt_count; i++) {
- if (!lov->lov_tgts[i])
- continue;
-
- /* Skip quota check on the administratively disabled OSTs. */
- if (!lov->lov_tgts[i]->ltd_activate) {
- CWARN("lov idx %d was administratively disabled, "
- "skip quotacheck on it.\n", i);
- continue;
- }
-
- if (!lov->lov_tgts[i]->ltd_active) {
- CERROR("lov idx %d inactive\n", i);
- rc = -EIO;
- goto out;
- }
- }
-
- for (i = 0; i < lov->desc.ld_tgt_count; i++) {
- int err;
-
- if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_activate)
- continue;
-
- err = obd_quotacheck(lov->lov_tgts[i]->ltd_exp, oqctl);
- if (err && !rc)
- rc = err;
- }
-
-out:
- obd_putref(obd);
-
- RETURN(rc);
-}
}
#endif /* __KERNEL__ */
#endif
-
-int client_quota_ctl(struct obd_device *unused, struct obd_export *exp,
- struct obd_quotactl *oqctl)
-{
- struct ptlrpc_request *req;
- struct obd_quotactl *oqc;
- const struct req_format *rf;
- int ver, opc, rc;
- ENTRY;
-
- if (!strcmp(exp->exp_obd->obd_type->typ_name, LUSTRE_MDC_NAME)) {
- rf = &RQF_MDS_QUOTACTL;
- ver = LUSTRE_MDS_VERSION,
- opc = MDS_QUOTACTL;
- } else if (!strcmp(exp->exp_obd->obd_type->typ_name, LUSTRE_OSC_NAME)) {
- rf = &RQF_OST_QUOTACTL;
- ver = LUSTRE_OST_VERSION,
- opc = OST_QUOTACTL;
- } else {
- RETURN(-EINVAL);
- }
-
- req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp), rf, ver, opc);
- if (req == NULL)
- RETURN(-ENOMEM);
-
- oqc = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
- *oqc = *oqctl;
-
- ptlrpc_request_set_replen(req);
- ptlrpc_at_set_req_timeout(req);
- req->rq_no_resend = 1;
-
- rc = ptlrpc_queue_wait(req);
- if (rc)
- CERROR("ptlrpc_queue_wait failed, rc: %d\n", rc);
-
- if (req->rq_repmsg &&
- (oqc = req_capsule_server_get(&req->rq_pill, &RMF_OBD_QUOTACTL))) {
- *oqctl = *oqc;
- } else if (!rc) {
- CERROR ("Can't unpack obd_quotactl\n");
- rc = -EPROTO;
- }
-
- EXIT;
-
- ptlrpc_req_finished(req);
-
- return rc;
-}
-
-/**
- * For lmv, only need to send request to master MDT, and the master MDT will
- * process with other slave MDTs.
- */
-int lmv_quota_ctl(struct obd_device *unused, struct obd_export *exp,
- struct obd_quotactl *oqctl)
-{
- struct obd_device *obd = class_exp2obd(exp);
- struct lmv_obd *lmv = &obd->u.lmv;
- struct lmv_tgt_desc *tgt = &lmv->tgts[0];
- int rc = 0, i;
- __u64 curspace;
- __u64 curinodes;
- ENTRY;
-
- if (!lmv->desc.ld_tgt_count || !tgt->ltd_active) {
- CERROR("master lmv inactive\n");
- RETURN(-EIO);
- }
-
- if (oqctl->qc_cmd != Q_GETOQUOTA) {
- rc = obd_quotactl(tgt->ltd_exp, oqctl);
- RETURN(rc);
- }
-
- curspace = curinodes = 0;
- for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
- int err;
- tgt = &lmv->tgts[i];
-
- if (tgt->ltd_exp == NULL)
- continue;
- if (!tgt->ltd_active) {
- CDEBUG(D_HA, "mdt %d is inactive.\n", i);
- continue;
- }
-
- err = obd_quotactl(tgt->ltd_exp, oqctl);
- if (err) {
- CERROR("getquota on mdt %d failed. %d\n", i, err);
- if (!rc)
- rc = err;
- } else {
- curspace += oqctl->qc_dqblk.dqb_curspace;
- curinodes += oqctl->qc_dqblk.dqb_curinodes;
- }
- }
- oqctl->qc_dqblk.dqb_curspace = curspace;
- oqctl->qc_dqblk.dqb_curinodes = curinodes;
-
- RETURN(rc);
-}
-
-int lov_quota_ctl(struct obd_device *unused, struct obd_export *exp,
- struct obd_quotactl *oqctl)
-{
- struct obd_device *obd = class_exp2obd(exp);
- struct lov_obd *lov = &obd->u.lov;
- struct lov_tgt_desc *tgt;
- __u64 curspace = 0;
- __u64 bhardlimit = 0;
- int i, rc = 0;
- ENTRY;
-
- if (oqctl->qc_cmd != LUSTRE_Q_QUOTAON &&
- oqctl->qc_cmd != LUSTRE_Q_QUOTAOFF &&
- oqctl->qc_cmd != Q_GETOQUOTA &&
- oqctl->qc_cmd != Q_INITQUOTA &&
- oqctl->qc_cmd != LUSTRE_Q_SETQUOTA &&
- oqctl->qc_cmd != Q_FINVALIDATE) {
- CERROR("bad quota opc %x for lov obd", oqctl->qc_cmd);
- RETURN(-EFAULT);
- }
-
- /* for lov tgt */
- obd_getref(obd);
- for (i = 0; i < lov->desc.ld_tgt_count; i++) {
- int err;
-
- tgt = lov->lov_tgts[i];
-
- if (!tgt)
- continue;
-
- if (!tgt->ltd_active || tgt->ltd_reap) {
- if (oqctl->qc_cmd == Q_GETOQUOTA &&
- lov->lov_tgts[i]->ltd_activate) {
- rc = -EREMOTEIO;
- CERROR("ost %d is inactive\n", i);
- } else {
- CDEBUG(D_HA, "ost %d is inactive\n", i);
- }
- continue;
- }
-
- err = obd_quotactl(tgt->ltd_exp, oqctl);
- if (err) {
- if (tgt->ltd_active && !rc)
- rc = err;
- continue;
- }
-
- if (oqctl->qc_cmd == Q_GETOQUOTA) {
- curspace += oqctl->qc_dqblk.dqb_curspace;
- bhardlimit += oqctl->qc_dqblk.dqb_bhardlimit;
- }
- }
- obd_putref(obd);
-
- if (oqctl->qc_cmd == Q_GETOQUOTA) {
- oqctl->qc_dqblk.dqb_curspace = curspace;
- oqctl->qc_dqblk.dqb_bhardlimit = bhardlimit;
- }
- RETURN(rc);
-}
#endif /* HAVE_QUOTA_SUPPORT */
#endif /* __KERNEL__ */
-struct osc_quota_info {
- cfs_list_t oqi_hash; /* hash list */
- struct client_obd *oqi_cli; /* osc obd */
- unsigned int oqi_id; /* uid/gid of a file */
- short oqi_type; /* quota type */
-};
-
-cfs_spinlock_t qinfo_list_lock = CFS_SPIN_LOCK_UNLOCKED;
-
-static cfs_list_t qinfo_hash[NR_DQHASH];
-/* SLAB cache for client quota context */
-cfs_mem_cache_t *qinfo_cachep = NULL;
-
-static inline int hashfn(struct client_obd *cli, unsigned long id, int type)
- __attribute__((__const__));
-
-static inline int hashfn(struct client_obd *cli, unsigned long id, int type)
-{
- unsigned long tmp = ((unsigned long)cli>>6) ^ id;
- tmp = (tmp * (MAXQUOTAS - type)) % NR_DQHASH;
- return tmp;
-}
-
-/* caller must hold qinfo_list_lock */
-static inline void insert_qinfo_hash(struct osc_quota_info *oqi)
-{
- cfs_list_t *head = qinfo_hash +
- hashfn(oqi->oqi_cli, oqi->oqi_id, oqi->oqi_type);
-
- LASSERT_SPIN_LOCKED(&qinfo_list_lock);
- cfs_list_add(&oqi->oqi_hash, head);
-}
-
-/* caller must hold qinfo_list_lock */
-static inline void remove_qinfo_hash(struct osc_quota_info *oqi)
-{
- LASSERT_SPIN_LOCKED(&qinfo_list_lock);
- cfs_list_del_init(&oqi->oqi_hash);
-}
-
-/* caller must hold qinfo_list_lock */
-static inline struct osc_quota_info *find_qinfo(struct client_obd *cli,
- unsigned int id, int type)
-{
- unsigned int hashent = hashfn(cli, id, type);
- struct osc_quota_info *oqi;
- ENTRY;
-
- LASSERT_SPIN_LOCKED(&qinfo_list_lock);
- cfs_list_for_each_entry(oqi, &qinfo_hash[hashent], oqi_hash) {
- if (oqi->oqi_cli == cli &&
- oqi->oqi_id == id && oqi->oqi_type == type)
- return oqi;
- }
- RETURN(NULL);
-}
-
-static struct osc_quota_info *alloc_qinfo(struct client_obd *cli,
- unsigned int id, int type)
-{
- struct osc_quota_info *oqi;
- ENTRY;
-
- OBD_SLAB_ALLOC(oqi, qinfo_cachep, CFS_ALLOC_IO, sizeof(*oqi));
- if(!oqi)
- RETURN(NULL);
-
- CFS_INIT_LIST_HEAD(&oqi->oqi_hash);
- oqi->oqi_cli = cli;
- oqi->oqi_id = id;
- oqi->oqi_type = type;
-
- RETURN(oqi);
-}
-
-static void free_qinfo(struct osc_quota_info *oqi)
-{
- OBD_SLAB_FREE(oqi, qinfo_cachep, sizeof(*oqi));
-}
-
-int osc_quota_chkdq(struct client_obd *cli, const unsigned int qid[])
-{
- unsigned int id;
- int cnt, rc = QUOTA_OK;
- ENTRY;
-
- cfs_spin_lock(&qinfo_list_lock);
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- struct osc_quota_info *oqi = NULL;
-
- id = (cnt == USRQUOTA) ? qid[USRQUOTA] : qid[GRPQUOTA];
- oqi = find_qinfo(cli, id, cnt);
- if (oqi) {
- rc = NO_QUOTA;
- break;
- }
- }
- cfs_spin_unlock(&qinfo_list_lock);
-
- if (rc == NO_QUOTA)
- CDEBUG(D_QUOTA, "chkdq found noquota for %s %d\n",
- cnt == USRQUOTA ? "user" : "group", id);
- RETURN(rc);
-}
-
-int osc_quota_setdq(struct client_obd *cli, const unsigned int qid[],
- obd_flag valid, obd_flag flags)
-{
- unsigned int id;
- obd_flag noquota;
- int cnt, rc = 0;
- ENTRY;
-
-
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- struct osc_quota_info *oqi = NULL, *old;
-
- if (!(valid & ((cnt == USRQUOTA) ?
- OBD_MD_FLUSRQUOTA : OBD_MD_FLGRPQUOTA)))
- continue;
-
- id = (cnt == USRQUOTA) ? qid[USRQUOTA] : qid[GRPQUOTA];
- noquota = (cnt == USRQUOTA) ?
- (flags & OBD_FL_NO_USRQUOTA) : (flags & OBD_FL_NO_GRPQUOTA);
-
- if (noquota) {
- oqi = alloc_qinfo(cli, id, cnt);
- if (!oqi) {
- rc = -ENOMEM;
- CDEBUG(D_QUOTA, "setdq for %s %d failed, "
- "(rc = %d)\n",
- cnt == USRQUOTA ? "user" : "group",
- id, rc);
- break;
- }
- }
-
- cfs_spin_lock(&qinfo_list_lock);
- old = find_qinfo(cli, id, cnt);
- if (old && !noquota)
- remove_qinfo_hash(old);
- else if (!old && noquota)
- insert_qinfo_hash(oqi);
- cfs_spin_unlock(&qinfo_list_lock);
-
- if (old && !noquota)
- CDEBUG(D_QUOTA, "setdq to remove for %s %d\n",
- cnt == USRQUOTA ? "user" : "group", id);
- else if (!old && noquota)
- CDEBUG(D_QUOTA, "setdq to insert for %s %d\n",
- cnt == USRQUOTA ? "user" : "group", id);
-
- if (old) {
- if (noquota)
- free_qinfo(oqi);
- else
- free_qinfo(old);
- }
- }
-
- RETURN(rc);
-}
-
-int osc_quota_cleanup(struct obd_device *obd)
-{
- struct client_obd *cli = &obd->u.cli;
- struct osc_quota_info *oqi, *n;
- int i;
- ENTRY;
-
- cfs_spin_lock(&qinfo_list_lock);
- for (i = 0; i < NR_DQHASH; i++) {
- cfs_list_for_each_entry_safe(oqi, n, &qinfo_hash[i], oqi_hash) {
- if (oqi->oqi_cli != cli)
- continue;
- remove_qinfo_hash(oqi);
- free_qinfo(oqi);
- }
- }
- cfs_spin_unlock(&qinfo_list_lock);
-
- RETURN(0);
-}
-
-int osc_quota_init(void)
-{
- int i;
- ENTRY;
-
- LASSERT(qinfo_cachep == NULL);
- qinfo_cachep = cfs_mem_cache_create("osc_quota_info",
- sizeof(struct osc_quota_info),
- 0, 0);
- if (!qinfo_cachep)
- RETURN(-ENOMEM);
-
- for (i = 0; i < NR_DQHASH; i++)
- CFS_INIT_LIST_HEAD(qinfo_hash + i);
-
- RETURN(0);
-}
-
-int osc_quota_exit(void)
-{
- struct osc_quota_info *oqi, *n;
- int i, rc;
- ENTRY;
-
- cfs_spin_lock(&qinfo_list_lock);
- for (i = 0; i < NR_DQHASH; i++) {
- cfs_list_for_each_entry_safe(oqi, n, &qinfo_hash[i], oqi_hash) {
- remove_qinfo_hash(oqi);
- free_qinfo(oqi);
- }
- }
- cfs_spin_unlock(&qinfo_list_lock);
-
- rc = cfs_mem_cache_destroy(qinfo_cachep);
- LASSERTF(rc == 0, "couldn't destory qinfo_cachep slab\n");
- qinfo_cachep = NULL;
-
- RETURN(0);
-}
-
#ifdef __KERNEL__
#ifdef HAVE_QUOTA_SUPPORT
quota_interface_t mds_quota_interface = {
#endif
#endif /* __KERNEL__ */
-quota_interface_t mdc_quota_interface = {
- .quota_ctl = client_quota_ctl,
- .quota_check = client_quota_check,
- .quota_poll_check = client_quota_poll_check,
-};
-
-quota_interface_t lmv_quota_interface = {
- .quota_ctl = lmv_quota_ctl,
- .quota_check = lmv_quota_check,
-};
-
-quota_interface_t osc_quota_interface = {
- .quota_ctl = client_quota_ctl,
- .quota_check = client_quota_check,
- .quota_poll_check = client_quota_poll_check,
- .quota_init = osc_quota_init,
- .quota_exit = osc_quota_exit,
- .quota_chkdq = osc_quota_chkdq,
- .quota_setdq = osc_quota_setdq,
- .quota_cleanup = osc_quota_cleanup,
- .quota_adjust_qunit = client_quota_adjust_qunit,
-};
-
-quota_interface_t lov_quota_interface = {
- .quota_ctl = lov_quota_ctl,
- .quota_check = lov_quota_check,
- .quota_adjust_qunit = lov_quota_adjust_qunit,
-};
-
#ifdef __KERNEL__
cfs_proc_dir_entry_t *lquota_type_proc_dir = NULL;
PORTAL_SYMBOL_REGISTER(filter_quota_interface);
PORTAL_SYMBOL_REGISTER(mds_quota_interface);
#endif
- PORTAL_SYMBOL_REGISTER(mdc_quota_interface);
- PORTAL_SYMBOL_REGISTER(lmv_quota_interface);
- PORTAL_SYMBOL_REGISTER(osc_quota_interface);
- PORTAL_SYMBOL_REGISTER(lov_quota_interface);
return 0;
}
static void /*__exit*/ exit_lustre_quota(void)
{
- PORTAL_SYMBOL_UNREGISTER(mdc_quota_interface);
- PORTAL_SYMBOL_UNREGISTER(lmv_quota_interface);
- PORTAL_SYMBOL_UNREGISTER(osc_quota_interface);
- PORTAL_SYMBOL_UNREGISTER(lov_quota_interface);
#ifdef HAVE_QUOTA_SUPPORT
PORTAL_SYMBOL_UNREGISTER(filter_quota_interface);
PORTAL_SYMBOL_UNREGISTER(mds_quota_interface);
EXPORT_SYMBOL(mds_quota_interface);
EXPORT_SYMBOL(filter_quota_interface);
#endif
-EXPORT_SYMBOL(mdc_quota_interface);
-EXPORT_SYMBOL(lmv_quota_interface);
-EXPORT_SYMBOL(osc_quota_interface);
-EXPORT_SYMBOL(lov_quota_interface);
#endif /* __KERNEL */