From b54b7ce43929ce7ff6e48cd219623c264ca6b6b3 Mon Sep 17 00:00:00 2001 From: Hongchao Zhang Date: Wed, 15 Dec 2021 20:11:17 +0800 Subject: [PATCH] LU-14472 quota: skip non-exist or inact tgt for lfs_quota The nonexistent or inactive targets (MDC or OSC) should be skipped for "lfs quota". Change-Id: I25eece413715e4e05dd94ccbfd101220da7477f9 Signed-off-by: Hongchao Zhang Reviewed-on: https://review.whamcloud.com/41771 Tested-by: jenkins Reviewed-by: Andreas Dilger Tested-by: Maloo Reviewed-by: Feng, Lei Reviewed-by: Oleg Drokin --- lustre/doc/lfs-quota.1 | 1 + lustre/llite/dir.c | 55 ++++++++++++----------- lustre/lmv/lmv_obd.c | 15 ++++++- lustre/lov/lov_obd.c | 87 ++++++++++++++++++++---------------- lustre/tests/sanity-quota.sh | 102 +++++++++++++++++++++++++++++++++++++++++++ lustre/utils/lfs.c | 22 ++++++++++ 6 files changed, 214 insertions(+), 68 deletions(-) diff --git a/lustre/doc/lfs-quota.1 b/lustre/doc/lfs-quota.1 index bab4ad0..18d8761 100644 --- a/lustre/doc/lfs-quota.1 +++ b/lustre/doc/lfs-quota.1 @@ -52,6 +52,7 @@ Verbose. Display per-MDT and per-OST statistics in addition to the usual system wide data. An asterisk near the OST or MDT means that the quota is exceeded only for that specific target. The user is over the quota only if an asterisk is near the whole filesystem usage. +Inactive target will also be printed but marked as "inact". .TP .B -u <\fIuname|uid\fR> Display user quota information for \fIuname\fR or \fIuid\fR. diff --git a/lustre/llite/dir.c b/lustre/llite/dir.c index 7f77d31..a20cf3e 100644 --- a/lustre/llite/dir.c +++ b/lustre/llite/dir.c @@ -1239,34 +1239,33 @@ int quotactl_ioctl(struct super_block *sb, struct if_quotactl *qctl) else RETURN(-EINVAL); - switch (valid) { - case QC_MDTIDX: - rc = obd_iocontrol(OBD_IOC_QUOTACTL, sbi->ll_md_exp, - sizeof(*qctl), qctl, NULL); - break; - case QC_OSTIDX: - rc = obd_iocontrol(OBD_IOC_QUOTACTL, sbi->ll_dt_exp, - sizeof(*qctl), qctl, NULL); - break; - case QC_UUID: - rc = obd_iocontrol(OBD_IOC_QUOTACTL, sbi->ll_md_exp, - sizeof(*qctl), qctl, NULL); - if (rc == -EAGAIN) - rc = obd_iocontrol(OBD_IOC_QUOTACTL, - sbi->ll_dt_exp, - sizeof(*qctl), qctl, NULL); - break; - default: - rc = -EINVAL; - break; - } - - if (rc) - RETURN(rc); + switch (valid) { + case QC_MDTIDX: + rc = obd_iocontrol(OBD_IOC_QUOTACTL, sbi->ll_md_exp, + sizeof(*qctl), qctl, NULL); + break; + case QC_OSTIDX: + rc = obd_iocontrol(OBD_IOC_QUOTACTL, sbi->ll_dt_exp, + sizeof(*qctl), qctl, NULL); + break; + case QC_UUID: + rc = obd_iocontrol(OBD_IOC_QUOTACTL, sbi->ll_md_exp, + sizeof(*qctl), qctl, NULL); + if (rc == -EAGAIN) + rc = obd_iocontrol(OBD_IOC_QUOTACTL, + sbi->ll_dt_exp, + sizeof(*qctl), qctl, NULL); + break; + default: + rc = -EINVAL; + break; + } - qctl->qc_cmd = cmd; - } else { - struct obd_quotactl *oqctl; + qctl->qc_cmd = cmd; + if (rc) + RETURN(rc); + } else { + struct obd_quotactl *oqctl; int oqctl_len = sizeof(*oqctl); if (LUSTRE_Q_CMD_IS_POOL(cmd)) @@ -2033,7 +2032,7 @@ out_req: } rc = quotactl_ioctl(inode->i_sb, qctl); - if (rc == 0 && + if ((rc == 0 || rc == -ENODATA) && copy_to_user((void __user *)arg, qctl, sizeof(*qctl))) rc = -EFAULT; diff --git a/lustre/lmv/lmv_obd.c b/lustre/lmv/lmv_obd.c index 9de2f12..4fded87 100644 --- a/lustre/lmv/lmv_obd.c +++ b/lustre/lmv/lmv_obd.c @@ -864,6 +864,7 @@ static int lmv_iocontrol(unsigned int cmd, struct obd_export *exp, case OBD_IOC_QUOTACTL: { struct if_quotactl *qctl = karg; struct obd_quotactl *oqctl; + struct obd_import *imp; if (qctl->qc_valid == QC_MDTIDX) { tgt = lmv_tgt(lmv, qctl->qc_idx); @@ -882,9 +883,19 @@ static int lmv_iocontrol(unsigned int cmd, struct obd_export *exp, RETURN(-EINVAL); } - if (!tgt || !tgt->ltd_exp) + if (!tgt) + RETURN(-ENODEV); + + if (!tgt->ltd_exp) RETURN(-EINVAL); + imp = class_exp2cliimp(tgt->ltd_exp); + if (!tgt->ltd_active && imp->imp_state != LUSTRE_IMP_IDLE) { + qctl->qc_valid = QC_MDTIDX; + qctl->obd_uuid = tgt->ltd_uuid; + RETURN(-ENODATA); + } + OBD_ALLOC_PTR(oqctl); if (!oqctl) RETURN(-ENOMEM); @@ -3180,7 +3191,7 @@ static int lmv_get_info(const struct lu_env *env, struct obd_export *exp, exp->exp_connect_data = *(struct obd_connect_data *)val; RETURN(rc); } else if (KEY_IS(KEY_TGT_COUNT)) { - *((int *)val) = lmv->lmv_mdt_descs.ltd_lmv_desc.ld_tgt_count; + *((int *)val) = lmv->lmv_mdt_descs.ltd_tgts_size; RETURN(0); } diff --git a/lustre/lov/lov_obd.c b/lustre/lov/lov_obd.c index b7512bd..c566774 100644 --- a/lustre/lov/lov_obd.c +++ b/lustre/lov/lov_obd.c @@ -1002,54 +1002,65 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len, sizeof(struct obd_statfs)))) RETURN(-EFAULT); break; - } - case OBD_IOC_QUOTACTL: { - struct if_quotactl *qctl = karg; - struct lov_tgt_desc *tgt = NULL; - struct obd_quotactl *oqctl; + } + case OBD_IOC_QUOTACTL: { + struct if_quotactl *qctl = karg; + struct lov_tgt_desc *tgt = NULL; + struct obd_quotactl *oqctl; + struct obd_import *imp; if (qctl->qc_valid == QC_OSTIDX) { if (count <= qctl->qc_idx) RETURN(-EINVAL); tgt = lov->lov_tgts[qctl->qc_idx]; - if (!tgt || !tgt->ltd_exp) + if (!tgt) + RETURN(-ENODEV); + + if (!tgt->ltd_exp) RETURN(-EINVAL); - } else if (qctl->qc_valid == QC_UUID) { - for (i = 0; i < count; i++) { - tgt = lov->lov_tgts[i]; - if (!tgt || - !obd_uuid_equals(&tgt->ltd_uuid, - &qctl->obd_uuid)) - continue; - - if (tgt->ltd_exp == NULL) - RETURN(-EINVAL); - - break; - } - } else { - RETURN(-EINVAL); - } + } else if (qctl->qc_valid == QC_UUID) { + for (i = 0; i < count; i++) { + tgt = lov->lov_tgts[i]; + if (!tgt || + !obd_uuid_equals(&tgt->ltd_uuid, + &qctl->obd_uuid)) + continue; + + if (tgt->ltd_exp == NULL) + RETURN(-EINVAL); + + break; + } + } else { + RETURN(-EINVAL); + } - if (i >= count) - RETURN(-EAGAIN); + if (i >= count) + RETURN(-EAGAIN); - LASSERT(tgt && tgt->ltd_exp); - OBD_ALLOC_PTR(oqctl); - if (!oqctl) - RETURN(-ENOMEM); + LASSERT(tgt && tgt->ltd_exp); + imp = class_exp2cliimp(tgt->ltd_exp); + if (!tgt->ltd_active && imp->imp_state != LUSTRE_IMP_IDLE) { + qctl->qc_valid = QC_OSTIDX; + qctl->obd_uuid = tgt->ltd_uuid; + RETURN(-ENODATA); + } - QCTL_COPY(oqctl, qctl); - rc = obd_quotactl(tgt->ltd_exp, oqctl); - if (rc == 0) { - QCTL_COPY(qctl, oqctl); - qctl->qc_valid = QC_OSTIDX; - qctl->obd_uuid = tgt->ltd_uuid; - } - OBD_FREE_PTR(oqctl); - break; - } + OBD_ALLOC_PTR(oqctl); + if (!oqctl) + RETURN(-ENOMEM); + + QCTL_COPY(oqctl, qctl); + rc = obd_quotactl(tgt->ltd_exp, oqctl); + if (rc == 0) { + QCTL_COPY(qctl, oqctl); + qctl->qc_valid = QC_OSTIDX; + qctl->obd_uuid = tgt->ltd_uuid; + } + OBD_FREE_PTR(oqctl); + break; + } default: { int set = 0; diff --git a/lustre/tests/sanity-quota.sh b/lustre/tests/sanity-quota.sh index a4a33ba..0b5e2f3 100755 --- a/lustre/tests/sanity-quota.sh +++ b/lustre/tests/sanity-quota.sh @@ -2558,6 +2558,108 @@ test_15(){ } run_test 15 "Set over 4T block quota" +test_16a() +{ + (( $CLIENT_VERSION < $(version_code 2.14.55) )) && + skip "Not supported Lustre client before 2.14.55" + + setup_quota_test || error "setup quota failed with $?" + + $LFS setquota -u $TSTUSR -B 500M -I 10K $MOUNT || + error "failed to set quota for user $TSTUSR" + $LFS setquota -g $TSTUSR -B 500M -I 10K $MOUNT || + error "failed to set quota for group $TSTUSR" + + $RUNAS $DD of=$DIR/$tdir/$tfile bs=1M count=50 || + quota_error u $TSTUSR "write failure" + + $LFS quota -u $TSTUSR $MOUNT || + quota_error u $TSTUSR "failed to get quota" + + local OSC=$($LCTL dl | grep OST0000-osc-[^M] | awk '{print $4}') + + $LCTL --device %$OSC deactivate + stack_trap "$LCTL --device %$OSC activate" + + $LFS quota -v -u $TSTUSR $MOUNT || + quota_error u $TSTUSR "failed to get quota after deactivate OSC" + $LFS quota -v -g $TSTUSR $MOUNT || + quota_error g $TSTUSR "failed to get quota after deactivate OSC" + + (( $MDSCOUNT > 1 )) || return 0 + + local MDC=$($LCTL dl | grep MDT0001-mdc-[^M] | awk '{print $4}') + + $LCTL --device %$MDC deactivate + stack_trap "$LCTL --device %$MDC activate" + + $LFS quota -v -u $TSTUSR $MOUNT || + quota_error u $TSTUSR "failed to get quota after deactivate MDC" + $LFS quota -v -g $TSTUSR $MOUNT || + quota_error g $TSTUSR "failed to get quota after deactivate OSC" +} +run_test 16a "lfs quota should skip the inactive MDT/OST" + +cleanup_16b() +{ + stopall + formatall + setupall +} + +test_16b() +{ + (( $CLIENT_VERSION < $(version_code 2.14.55) )) && + skip "Not supported Lustre client before 2.14.55" + + (( $MDSCOUNT >= 3 )) || skip "needs >= 3 MDTs" + + stopall + if ! combined_mgs_mds ; then + format_mgs + start_mgs + fi + + add mds1 $(mkfs_opts mds1 $(mdsdevname 1)) --index=0 --reformat \ + $(mdsdevname 1) $(mdsvdevname 1) + add mds2 $(mkfs_opts mds2 $(mdsdevname 2)) --index=1 --reformat \ + $(mdsdevname 2) $(mdsvdevname 2) + add mds3 $(mkfs_opts mds3 $(mdsdevname 3)) --index=100 --reformat \ + $(mdsdevname 3) $(mdsvdevname 3) + + add ost1 $(mkfs_opts ost1 $(ostdevname 1)) --index=0 --reformat \ + $(ostdevname 1) $(ostvdevname 1) + add ost2 $(mkfs_opts ost2 $(ostdevname 2)) --index=100 --reformat \ + $(ostdevname 2) $(ostvdevname 2) + + stack_trap cleanup_16b + + start mds1 $(mdsdevname 1) $MDS_MOUNT_OPTS || error "MDT1 start failed" + start mds2 $(mdsdevname 2) $MDS_MOUNT_OPTS || error "MDT2 start failed" + start mds3 $(mdsdevname 3) $MDS_MOUNT_OPTS || error "MDT3 start failed" + start ost1 $(ostdevname 1) $OST_MOUNT_OPTS || error "OST1 start failed" + start ost2 $(ostdevname 2) $OST_MOUNT_OPTS || error "OST2 start failed" + + mount_client $MOUNT || error "Unable to mount client" + + setup_quota_test || error "setup quota failed with $?" + stack_trap cleanup_quota_test EXIT + + $LFS setquota -u $TSTUSR -B 100M -I 10K $MOUNT || + error "failed to set quota for user $TSTUSR" + $LFS setquota -g $TSTUSR -B 100M -I 10K $MOUNT || + error "failed to set quota for group $TSTUSR" + + $RUNAS $DD of=$DIR/$tdir/$tfile bs=1M count=10 || + quota_error u $TSTUSR "write failure" + + cnt=$($LFS quota -v -u $TSTUSR $MOUNT | grep -ce "^$FSNAME-[MD|OS]T*") + [ $cnt -le 5 ] || quota_error u $TSTUSR "failed to get user quota" + cnt=$($LFS quota -v -g $TSTUSR $MOUNT | grep -ce "^$FSNAME-[MD|OS]T*") + [ $cnt -le 5 ] || quota_error g $TSTUSR "failed to get group quota" +} +run_test 16b "lfs quota should skip the nonexistent MDT/OST" + test_17sub() { local err_code=$1 local BLKS=1 # 1M less than limit diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index 116fda3..68a74da 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -8308,6 +8308,28 @@ static int print_obd_quota(char *mnt, struct if_quotactl *qctl, int is_mdt, goto out; } + /* no target for this index yet */ + if (rc == -ENODEV) { + rc = 0; + continue; + } + + /* inactive target */ + if (rc == -ENODATA) { + char name[UUID_MAX+8]; + + snprintf(name, sizeof(name), "%s[inact]", + obd_uuid2str(&qctl->obd_uuid)); + memset(&qctl->qc_dqinfo, 0, + sizeof(qctl->qc_dqinfo)); + memset(&qctl->qc_dqblk, 0, + sizeof(qctl->qc_dqblk)); + print_quota(name, qctl, qctl->qc_valid, 0, h, + false); + rc = 0; + continue; + } + if (!rc1) rc1 = rc; fprintf(stderr, "quotactl %s%d failed.\n", -- 1.8.3.1