From: Andrew Perepechko Date: Wed, 16 Dec 2009 00:31:19 +0000 (+0300) Subject: b=21147 be tolerant to setting the same type and version of quota X-Git-Tag: v1_8_1_58~25 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=a16975493621a7866d576d75edd5d1cb6b6ece86;p=fs%2Flustre-release.git b=21147 be tolerant to setting the same type and version of quota i=Johann Lombardi i=ZhiYong Tian --- diff --git a/lustre/ChangeLog b/lustre/ChangeLog index 6f6e4ae..6742713 100644 --- a/lustre/ChangeLog +++ b/lustre/ChangeLog @@ -10,6 +10,11 @@ tbd Sun Microsystems, Inc. 2.6.16 - 2.6.30 vanilla (kernel.org) * Recommended e2fsprogs version: 1.41.6.sun1 +Severity : normal +Bugzilla : 21147 +Description: quota type and version is not tolerant to resetting + to the same value + Severity : enhancement Bugzilla : 21511 Description: Update kernel to SLES11 2.6.27.39-0.3.1. diff --git a/lustre/quota/lproc_quota.c b/lustre/quota/lproc_quota.c index 5a9c112..17c873c 100644 --- a/lustre/quota/lproc_quota.c +++ b/lustre/quota/lproc_quota.c @@ -235,22 +235,17 @@ int lprocfs_quota_rd_type(char *page, char **start, off_t off, int count, } EXPORT_SYMBOL(lprocfs_quota_rd_type); -static int auto_quota_on(struct obd_device *obd, int type, - struct super_block *sb, int is_master) +/* + * generic_quota_on is very lazy and tolerant about current quota settings + * @global means to turn on quotas on each OST additionally to local quotas; + * should not be called from filter_quota_ctl on MDS nodes (as it starts + * admin quotas on MDS nodes). + */ +int generic_quota_on(struct obd_device *obd, struct obd_quotactl *oqctl, int global) { - struct obd_quotactl *oqctl; + struct obd_device_target *obt = &obd->u.obt; struct lvfs_run_ctxt saved; - int rc = 0, id; - struct obd_device_target *obt; - ENTRY; - - LASSERT(type == USRQUOTA || type == GRPQUOTA || type == UGQUOTA); - - obt = &obd->u.obt; - - OBD_ALLOC_PTR(oqctl); - if (!oqctl) - RETURN(-ENOMEM); + int id, is_master, rc = 0, local; /* means we need a local quotaon */ if (!atomic_dec_and_test(&obt->obt_quotachecking)) { CDEBUG(D_INFO, "other people are doing quotacheck\n"); @@ -258,47 +253,68 @@ static int auto_quota_on(struct obd_device *obd, int type, RETURN(-EBUSY); } - id = UGQUOTA2LQC(type); - /* quota already turned on */ - if ((obt->obt_qctxt.lqc_flags & id) == id) { - rc = 0; - goto out; - } + id = UGQUOTA2LQC(oqctl->qc_type); + local = (obt->obt_qctxt.lqc_flags & id) != id; - oqctl->qc_type = type; oqctl->qc_cmd = Q_QUOTAON; oqctl->qc_id = obt->obt_qfmt; - push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); - if (is_master) { - struct mds_obd *mds = &obd->u.mds; - - down(&mds->mds_qonoff_sem); + is_master= !strcmp(obd->obd_type->typ_name, LUSTRE_MDS_NAME); + if (is_master && local) { + down(&obd->u.mds.mds_qonoff_sem); + push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); /* turn on cluster wide quota */ rc = mds_admin_quota_on(obd, oqctl); + pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); if (rc && rc != -ENOENT) - CERROR("%s: auto-enable admin quota failed. rc=%d\n", - obd->obd_name, rc); - up(&mds->mds_qonoff_sem); - + CERROR("%s: %s admin quotaon failed. rc=%d\n", + obd->obd_name, global ? "global" : "local", rc); } - if (!rc) { - /* turn on local quota */ - rc = fsfilt_quotactl(obd, sb, oqctl); - if (rc) { - if (rc != -ENOENT) - CERROR("%s: auto-enable local quota failed with" - " rc=%d\n", obd->obd_name, rc); - } else { - obt->obt_qctxt.lqc_flags |= UGQUOTA2LQC(type); + + if (rc == 0) { + if (local) { + push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); + /* turn on local quota */ + rc = fsfilt_quotactl(obd, obt->obt_sb, oqctl); + pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); + if (rc) { + if (rc != -ENOENT) + CERROR("%s: %s quotaon failed with" + " rc=%d\n", obd->obd_name, + global ? "global" : "local", rc); + } else { + obt->obt_qctxt.lqc_flags |= UGQUOTA2LQC(oqctl->qc_type); + } } + + if (rc == 0 && global && is_master) + rc = obd_quotactl(obd->u.mds.mds_osc_exp, oqctl); } - pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); + if (is_master) + up(&obd->u.mds.mds_qonoff_sem); -out: atomic_inc(&obt->obt_quotachecking); + return rc; +} + +static int auto_quota_on(struct obd_device *obd, int type) +{ + struct obd_quotactl *oqctl; + int rc; + ENTRY; + + LASSERT(type == USRQUOTA || type == GRPQUOTA || type == UGQUOTA); + + OBD_ALLOC_PTR(oqctl); + if (!oqctl) + RETURN(-ENOMEM); + + oqctl->qc_type = type; + + rc = generic_quota_on(obd, oqctl, 0); + OBD_FREE_PTR(oqctl); RETURN(rc); } @@ -418,7 +434,7 @@ int lprocfs_quota_wr_type(struct file *file, const char *buffer, } if (type != 0) { - int rc = auto_quota_on(obd, type - 1, obt->obt_sb, is_mds); + int rc = auto_quota_on(obd, type - 1); if (rc == 0) build_lqs(obd); diff --git a/lustre/quota/quota_ctl.c b/lustre/quota/quota_ctl.c index d17b2d1..afc0b0d 100644 --- a/lustre/quota/quota_ctl.c +++ b/lustre/quota/quota_ctl.c @@ -128,7 +128,6 @@ int mds_quota_ctl(struct obd_export *exp, struct obd_quotactl *oqctl) do_gettimeofday(&work_start); switch (oqctl->qc_cmd) { 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); @@ -193,8 +192,13 @@ int filter_quota_ctl(struct obd_export *exp, struct obd_quotactl *oqctl) do_gettimeofday(&work_start); switch (oqctl->qc_cmd) { - case Q_FINVALIDATE: case Q_QUOTAON: + oqctl->qc_id = obt->obt_qfmt; + rc = generic_quota_on(obd, oqctl, 0); + /* when quotaon, create lqs for every quota uid/gid b=18574 */ + build_lqs(obd); + break; + case Q_FINVALIDATE: case Q_QUOTAOFF: if (!atomic_dec_and_test(&obt->obt_quotachecking)) { CDEBUG(D_INFO, "other people are doing quotacheck\n"); @@ -226,18 +230,12 @@ int filter_quota_ctl(struct obd_export *exp, struct obd_quotactl *oqctl) if (oqctl->qc_stat == QUOTA_RECOVERING) quota_unbarrier(handle); - if (oqctl->qc_cmd == Q_QUOTAON || oqctl->qc_cmd == Q_QUOTAOFF || + if (oqctl->qc_cmd == Q_QUOTAOFF || oqctl->qc_cmd == Q_FINVALIDATE) { - if (!rc && oqctl->qc_cmd == Q_QUOTAON) - obt->obt_qctxt.lqc_flags |= UGQUOTA2LQC(oqctl->qc_type); if (!rc && oqctl->qc_cmd == Q_QUOTAOFF) obt->obt_qctxt.lqc_flags &= ~UGQUOTA2LQC(oqctl->qc_type); atomic_inc(&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 */ diff --git a/lustre/quota/quota_internal.h b/lustre/quota/quota_internal.h index b36f044..abb83b8 100644 --- a/lustre/quota/quota_internal.h +++ b/lustre/quota/quota_internal.h @@ -214,4 +214,6 @@ static inline int client_quota_should_resend(int resend, struct client_obd *cli) atomic_read(&cli->cl_quota_resends) > resend : 1; } +int generic_quota_on(struct obd_device *obd, struct obd_quotactl *oqctl, + int global); #endif diff --git a/lustre/quota/quota_master.c b/lustre/quota/quota_master.c index 912772f..c8b3ccd 100644 --- a/lustre/quota/quota_master.c +++ b/lustre/quota/quota_master.c @@ -633,9 +633,8 @@ int mds_quota_invalidate(struct obd_device *obd, struct obd_quotactl *oqctl) oqctl->qc_type != UGQUOTA) return -EINVAL; - push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); - down(&mds->mds_qonoff_sem); + push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); for (i = 0; i < MAXQUOTAS; i++) { struct file *fp; @@ -665,9 +664,8 @@ int mds_quota_invalidate(struct obd_device *obd, struct obd_quotactl *oqctl) } out: - up(&mds->mds_qonoff_sem); - pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); + up(&mds->mds_qonoff_sem); return rc; } @@ -683,16 +681,16 @@ int mds_quota_finvalidate(struct obd_device *obd, struct obd_quotactl *oqctl) oqctl->qc_type != UGQUOTA) RETURN(-EINVAL); - push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); down(&mds->mds_qonoff_sem); + push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); oqctl->qc_cmd = Q_FINVALIDATE; rc = fsfilt_quotactl(obd, obd->u.obt.obt_sb, oqctl); if (!rc) rc = obd_quotactl(mds->mds_lov_exp, oqctl); - up(&mds->mds_qonoff_sem); pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); + up(&mds->mds_qonoff_sem); return rc; } @@ -708,9 +706,8 @@ int init_admin_quotafiles(struct obd_device *obd, struct obd_quotactl *oqctl) int i, rc = 0; ENTRY; - push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); - down(&mds->mds_qonoff_sem); + push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); for (i = 0; i < MAXQUOTAS && !rc; i++) { struct file *fp; @@ -795,9 +792,10 @@ int init_admin_quotafiles(struct obd_device *obd, struct obd_quotactl *oqctl) filp_close(fp, 0); qinfo->qi_files[i] = NULL; } - up(&mds->mds_qonoff_sem); pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); + up(&mds->mds_qonoff_sem); + RETURN(rc); } @@ -836,18 +834,13 @@ int mds_admin_quota_on(struct obd_device *obd, struct obd_quotactl *oqctl) const char* quotafile = qinfo->qi_version == LUSTRE_QUOTA_V1? quotafiles_v1[i] : quotafiles_v2[i]; - if (!Q_TYPESET(oqctl, i)) + if (!Q_TYPESET(oqctl, i) || qinfo->qi_files[i] != NULL) continue; LASSERT(strlen(quotafile) + sizeof(prefix) <= sizeof(name)); sprintf(name, "%s%s", prefix, quotafile); - if (qinfo->qi_files[i] != NULL) { - rc = -EBUSY; - break; - } - fp = filp_open(name, O_RDWR, 0); /* handle transparent migration to 64 bit quota file */ if (IS_ERR(fp) && PTR_ERR(fp) == -ENOENT && @@ -910,9 +903,6 @@ int mds_admin_quota_off(struct obd_device *obd, int mds_quota_on(struct obd_device *obd, struct obd_quotactl *oqctl) { - struct mds_obd *mds = &obd->u.mds; - struct obd_device_target *obt = &obd->u.obt; - struct lvfs_run_ctxt saved; int rc; ENTRY; @@ -921,30 +911,8 @@ int mds_quota_on(struct obd_device *obd, struct obd_quotactl *oqctl) oqctl->qc_type != UGQUOTA) RETURN(-EINVAL); - if (!atomic_dec_and_test(&obt->obt_quotachecking)) { - CDEBUG(D_INFO, "other people are doing quotacheck\n"); - atomic_inc(&obt->obt_quotachecking); - RETURN(-EBUSY); - } - - down(&mds->mds_qonoff_sem); - push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); - rc = mds_admin_quota_on(obd, oqctl); - if (rc) - GOTO(out, rc); - - rc = fsfilt_quotactl(obd, obd->u.obt.obt_sb, oqctl); - if (!rc) - obt->obt_qctxt.lqc_flags |= UGQUOTA2LQC(oqctl->qc_type); - else - GOTO(out, rc); + rc = generic_quota_on(obd, oqctl, 1); - rc = obd_quotactl(mds->mds_lov_exp, oqctl); - -out: - pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); - up(&mds->mds_qonoff_sem); - atomic_inc(&obt->obt_quotachecking); RETURN(rc); }