QCTL_COPY(oqctl, qctl);
rc = obd_quotactl(sbi->ll_md_exp, oqctl);
if (rc) {
- if (rc != -EBUSY && cmd == Q_QUOTAON) {
+ if (rc != -EALREADY && cmd == Q_QUOTAON) {
oqctl->qc_cmd = Q_QUOTAOFF;
obd_quotactl(sbi->ll_md_exp, oqctl);
}
{
struct obd_quotactl *oqctl;
struct lvfs_run_ctxt saved;
- int rc = 0, id;
+ int rc = 0, rc1 = 0, id;
struct obd_device_target *obt = &obd->u.obt;
+ struct lustre_quota_ctxt *qctxt = &obt->obt_qctxt;
+ struct mds_obd *mds = NULL;
ENTRY;
LASSERT(type == USRQUOTA || type == GRPQUOTA || type == UGQUOTA);
oqctl->qc_id = obt->obt_qfmt;
push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
- if (is_master) {
- struct mds_obd *mds = &obd->u.mds;
+ if (is_master) {
+ mds = &obd->u.mds;
down(&mds->mds_qonoff_sem);
/* turn on cluster wide quota */
- rc = mds_admin_quota_on(obd, oqctl);
- if (rc)
- CDEBUG(rc == -ENOENT ? D_QUOTA : D_ERROR,
- "auto-enable admin quota failed. rc=%d\n", rc);
- up(&mds->mds_qonoff_sem);
-
+ rc1 = mds_admin_quota_on(obd, oqctl);
+ if (rc1 && rc1 != -EALREADY) {
+ CDEBUG(rc1 == -ENOENT ? D_QUOTA : D_ERROR,
+ "auto-enable admin quota failed. rc=%d\n", rc1);
+ GOTO(out_ctxt, rc1);
+ }
}
+
+ /* turn on local quota */
+ rc = fsfilt_quotactl(obd, sb, oqctl);
if (!rc) {
- /* turn on local quota */
- rc = fsfilt_quotactl(obd, sb, oqctl);
- if (rc)
- CDEBUG(rc == -ENOENT ? D_QUOTA : D_ERROR,
- "auto-enable local quota failed. rc=%d\n", rc);
- else
- obt->obt_qctxt.lqc_flags |= UGQUOTA2LQC(type);
+ obt->obt_qctxt.lqc_flags |= UGQUOTA2LQC(type);
+ build_lqs(obd);
+ } else if (rc == -EBUSY && quota_is_on(qctxt, oqctl)) {
+ CWARN("mds local quota[%d] is on already\n", oqctl->qc_type);
+ rc = -EALREADY;
+ } else {
+ CDEBUG(rc == -ENOENT ? D_QUOTA : D_ERROR,
+ "auto-enable local quota failed. rc=%d\n", rc);
+ if (rc1 == -EALREADY) {
+ oqctl->qc_cmd = Q_QUOTAOFF;
+ mds_admin_quota_off(obd, oqctl);
+ }
+ GOTO(out_ctxt, rc);
}
- pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
EXIT;
+out_ctxt:
+ if (mds != NULL)
+ up(&mds->mds_qonoff_sem);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
+
out:
up(&obt->obt_quotachecking);
OBD_FREE_PTR(oqctl);
if (type != 0) {
int rc = auto_quota_on(obd, type - 1, obt->obt_sb, is_mds);
- if (rc == 0)
- build_lqs(obd);
- else if (rc != -EALREADY)
+ if (rc && rc != -EALREADY)
return rc;
}
qta->qta_sb = obt->obt_sb;
qta->qta_sem = &obt->obt_quotachecking;
+ /* quotaoff firstly */
+ oqctl->qc_cmd = Q_QUOTAOFF;
if (!strcmp(obd->obd_type->typ_name, LUSTRE_MDS_NAME)) {
+ rc = do_mds_quota_off(obd, oqctl);
+ if (rc && rc != -EALREADY) {
+ CERROR("off quota on MDS failed: %d\n", rc);
+ GOTO(out, rc);
+ }
+
/* quota master */
rc = init_admin_quotafiles(obd, &qta->qta_oqctl);
if (rc) {
CERROR("init_admin_quotafiles failed: %d\n", rc);
GOTO(out, rc);
}
+ } else {
+ struct lvfs_run_ctxt saved;
+ struct lustre_quota_ctxt *qctxt = &obt->obt_qctxt;
+
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
+ rc = fsfilt_quotactl(obd, obt->obt_sb, oqctl);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
+ if (!rc) {
+ qctxt->lqc_flags &= ~UGQUOTA2LQC(oqctl->qc_type);
+ } else if (!quota_is_off(qctxt, oqctl)) {
+ CERROR("off quota on OSS failed: %d\n", rc);
+ GOTO(out, rc);
+ }
}
/* we get ref for exp because target_quotacheck_callback() will use this
}
/**
+ * When quotaon, build a lqs for every uid/gid who has been set limitation
+ * for quota. After quota_search_lqs, it will hold one ref for the lqs.
+ * It will be released when qctxt_cleanup() is executed b=18574
+ *
+ * Should be called with obt->obt_quotachecking held. b=20152
+ */
+void build_lqs(struct obd_device *obd)
+{
+ struct obd_device_target *obt = &obd->u.obt;
+ struct lustre_quota_ctxt *qctxt = &obt->obt_qctxt;
+ struct list_head id_list;
+ int i, rc;
+
+ LASSERT_SEM_LOCKED(&obt->obt_quotachecking);
+ INIT_LIST_HEAD(&id_list);
+ for (i = 0; i < MAXQUOTAS; i++) {
+ struct dquot_id *dqid, *tmp;
+
+#ifndef KERNEL_SUPPORTS_QUOTA_READ
+ rc = fsfilt_qids(obd, sb_dqopt(qctxt->lqc_sb)->files[i], NULL,
+ i, &id_list);
+#else
+ rc = fsfilt_qids(obd, NULL, sb_dqopt(qctxt->lqc_sb)->files[i],
+ i, &id_list);
+#endif
+ if (rc) {
+ CDEBUG(D_ERROR, "fail to get %s qids!\n",
+ i ? "group" : "user");
+ continue;
+ }
+
+ list_for_each_entry_safe(dqid, tmp, &id_list,
+ di_link) {
+ struct lustre_qunit_size *lqs;
+
+ list_del_init(&dqid->di_link);
+ lqs = quota_search_lqs(LQS_KEY(i, dqid->di_id),
+ qctxt, 1);
+ if (lqs && !IS_ERR(lqs)) {
+ lqs->lqs_flags |= dqid->di_flag;
+ lqs_putref(lqs);
+ } else {
+ CDEBUG(D_ERROR, "fail to create a lqs"
+ "(%s id: %u)!\n", i ? "group" : "user",
+ dqid->di_id);
+ }
+
+ OBD_FREE_PTR(dqid);
+ }
+ }
+}
+
+/**
* lqs<->qctxt hash operations
*/
#ifdef HAVE_QUOTA_SUPPORT
#ifdef __KERNEL__
-/* When quotaon, build a lqs for every uid/gid who has been set limitation
- * for quota. After quota_search_lqs, it will hold one ref for the lqs.
- * It will be released when qctxt_cleanup() is executed b=18574 */
-void build_lqs(struct obd_device *obd)
-{
- struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt;
- struct list_head id_list;
- int i, rc;
-
- INIT_LIST_HEAD(&id_list);
- for (i = 0; i < MAXQUOTAS; i++) {
- struct dquot_id *dqid, *tmp;
-
-#ifndef KERNEL_SUPPORTS_QUOTA_READ
- rc = fsfilt_qids(obd, sb_dqopt(qctxt->lqc_sb)->files[i], NULL,
- i, &id_list);
-#else
- rc = fsfilt_qids(obd, NULL, sb_dqopt(qctxt->lqc_sb)->files[i],
- i, &id_list);
-#endif
- if (rc) {
- CDEBUG(D_ERROR, "fail to get %s qids!\n",
- i ? "group" : "user");
- continue;
- }
-
- list_for_each_entry_safe(dqid, tmp, &id_list,
- di_link) {
- struct lustre_qunit_size *lqs;
-
- list_del_init(&dqid->di_link);
- lqs = quota_search_lqs(LQS_KEY(i, dqid->di_id),
- qctxt, 1);
- if (lqs && !IS_ERR(lqs)) {
- lqs->lqs_flags |= dqid->di_flag;
- lqs_putref(lqs);
- } else {
- CDEBUG(D_ERROR, "fail to create a lqs"
- "(%s id: %u)!\n", i ? "group" : "user",
- dqid->di_id);
- }
-
- OBD_FREE_PTR(dqid);
- }
- }
-}
-
int mds_quota_ctl(struct obd_device *obd, struct obd_export *unused,
struct obd_quotactl *oqctl)
{
case Q_QUOTAON:
oqctl->qc_id = obt->obt_qfmt; /* override qfmt version */
rc = mds_quota_on(obd, oqctl);
- /* when quotaon, create lqs for every quota uid/gid b=18574 */
- build_lqs(obd);
break;
case Q_QUOTAOFF:
oqctl->qc_id = obt->obt_qfmt; /* override qfmt version */
struct obd_device *obd = exp->exp_obd;
struct obd_device_target *obt = &obd->u.obt;
struct lvfs_run_ctxt saved;
- struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt;
+ struct lustre_quota_ctxt *qctxt = &obt->obt_qctxt;
struct lustre_qunit_size *lqs;
void *handle = NULL;
struct timeval work_start;
if (oqctl->qc_cmd == Q_QUOTAON || oqctl->qc_cmd == Q_QUOTAOFF ||
oqctl->qc_cmd == Q_FINVALIDATE) {
if (oqctl->qc_cmd == Q_QUOTAON) {
- if (!rc)
+ if (!rc) {
obt->obt_qctxt.lqc_flags |=
UGQUOTA2LQC(oqctl->qc_type);
- else if (rc == -EBUSY &&
- quota_is_on(qctxt, oqctl))
+ /* when quotaon, create lqs for every
+ * quota uid/gid b=18574 */
+ build_lqs(obd);
+ } else if (rc == -EBUSY &&
+ quota_is_on(qctxt, oqctl)) {
rc = -EALREADY;
+ }
} else if (oqctl->qc_cmd == Q_QUOTAOFF) {
if (!rc)
obt->obt_qctxt.lqc_flags &=
up(&obt->obt_quotachecking);
}
- /* when quotaon, create lqs for every quota uid/gid b=18574 */
- if (oqctl->qc_cmd == Q_QUOTAON)
- build_lqs(obd);
break;
case Q_SETQUOTA:
/* currently, it is only used for nullifying the quota */
int mds_admin_quota_on(struct obd_device *obd, struct obd_quotactl *oqctl);
int mds_quota_on(struct obd_device *obd, struct obd_quotactl *oqctl);
int mds_quota_off(struct obd_device *obd, struct obd_quotactl *oqctl);
+int do_mds_quota_off(struct obd_device *obd, struct obd_quotactl *oqctl);
int mds_admin_quota_off(struct obd_device *obd, struct obd_quotactl *oqctl);
int mds_set_dqinfo(struct obd_device *obd, struct obd_quotactl *oqctl);
int mds_get_dqinfo(struct obd_device *obd, struct obd_quotactl *oqctl);
rc1 = fsfilt_quotactl(obd, obd->u.obt.obt_sb, oqctl);
if (!rc1) {
qctxt->lqc_flags |= UGQUOTA2LQC(oqctl->qc_type);
+ /* when quotaon, create lqs for every quota uid/gid b=18574 */
+ build_lqs(obd);
} else if (rc1 == -EBUSY && quota_is_on(qctxt, oqctl)) {
CWARN("mds local quota[%d] is on already\n", oqctl->qc_type);
rc1 = -EALREADY;
}
oqctl->qc_cmd = Q_QUOTAON;
}
+
EXIT;
out:
return rc ? : (rc1 ? : rc2);
}
-int mds_quota_off(struct obd_device *obd, struct obd_quotactl *oqctl)
+/* with obt->obt_quotachecking held */
+int do_mds_quota_off(struct obd_device *obd, struct obd_quotactl *oqctl)
{
struct mds_obd *mds = &obd->u.mds;
struct obd_device_target *obt = &obd->u.obt;
int rc = 0, rc1 = 0, rc2 = 0, imm;
ENTRY;
+ LASSERT_SEM_LOCKED(&obt->obt_quotachecking);
+
imm = oqctl->qc_type & IMMQUOTA;
oqctl->qc_type &= ~IMMQUOTA;
oqctl->qc_type != UGQUOTA)
RETURN(-EINVAL);
- down(&obt->obt_quotachecking);
push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
down(&mds->mds_qonoff_sem);
/* close admin quota files */
out:
up(&mds->mds_qonoff_sem);
pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
- up(&obt->obt_quotachecking);
return rc ? : (rc1 ? : rc2);
}
+int mds_quota_off(struct obd_device *obd, struct obd_quotactl *oqctl)
+{
+ struct obd_device_target *obt = &obd->u.obt;
+ int rc;
+ ENTRY;
+
+ down(&obt->obt_quotachecking);
+ rc = do_mds_quota_off(obd, oqctl);
+ up(&obt->obt_quotachecking);
+ RETURN(rc);
+}
+
int mds_set_dqinfo(struct obd_device *obd, struct obd_quotactl *oqctl)
{
struct mds_obd *mds = &obd->u.mds;
# set quota
quota_init() {
- $LFS quotaoff -ug $DIR
$LFS quotacheck -ug $DIR
resetquota -u $TSTUSR
quota_fini()
{
$LFS quotaoff $DIR
- do_nodes $(comma_list $(nodes_list)) "lctl set_param debug=-quota"
+ do_nodes $(comma_list $(nodes_list)) "lctl set_param debug=-quota"
}
quota_fini
[ -n "$ver" -a "$ver" != "3" ] && error "wrong quota version specifier"
- $LFS quotaoff -ug $MOUNT # just in case
[ -n "$type" ] && { $LFS quotacheck -$type $MOUNT || error "quotacheck has failed"; }
do_facet mgs "lctl conf_param ${fsname}-MDT*.mdd.quota_type=$spec"
done
}
-mds_sanity_check () {
- local timeout=$1
+osc_ensure_active () {
+ local facet=$1
+ local type=$2
+ local timeout=$3
local period=0
while [ $period -lt $timeout ]; do
- count=$(do_facet $SINGLEMDS "lctl dl | grep 'osc.*mdtlov_UUID' | grep ' IN ' 2>/dev/null | wc -l")
+ count=$(do_facet $facet "lctl dl | grep '${FSNAME}-OST.*-osc-${type}' | grep ' IN ' 2>/dev/null | wc -l")
if [ $count -eq 0 ]; then
break
fi
log "Using TIMEOUT=$TIMEOUT"
- mds_sanity_check $TIMEOUT
+ osc_ensure_active $SINGLEMDS M $TIMEOUT
+ osc_ensure_active client c $TIMEOUT
if [ x"$(som_check)" = x"enabled" ]; then
ENABLE_QUOTA=""
mnt = argv[optind];
- memset(&qctl, 0, sizeof(qctl));
- qctl.qc_cmd = LUSTRE_Q_QUOTAOFF;
- qctl.qc_type = check_type;
- rc = llapi_quotactl(mnt, &qctl);
- if (rc && errno != EALREADY) {
- fprintf(stderr, "quota off failed: %s\n", strerror(errno));
- return rc;
- }
-
rc = llapi_quotacheck(mnt, check_type);
if (rc) {
fprintf(stderr, "quotacheck failed: %s\n", strerror(errno));