From: adilger Date: Wed, 1 Jun 2005 23:18:33 +0000 (+0000) Subject: Branch b1_4 X-Git-Tag: v1_7_100~1^25~8^2~64 X-Git-Url: https://git.whamcloud.com/gitweb?a=commitdiff_plain;h=f8ab79b857b6adde9df98eabb3c7ae64a1ec3e17;p=fs%2Flustre-release.git Branch b1_4 Some minor updates from b1_4_quota that I had in my tree for a long time. There are more updates that need to be landed, but these are pretty safe. --- diff --git a/lustre/include/linux/lustre_quota.h b/lustre/include/linux/lustre_quota.h index 7633ebe..91da654 100644 --- a/lustre/include/linux/lustre_quota.h +++ b/lustre/include/linux/lustre_quota.h @@ -10,9 +10,6 @@ #include #include -/* XXX disable amdin quotafile delete dquot temporarily */ -#define QFMT_NO_DELETE 1 - #define QUSG(count, isblk) (isblk ? toqb(count) : count) /* If the (quota limit < qunit * slave count), the slave which can't diff --git a/lustre/ldiskfs/lustre_quota_fmt.c b/lustre/ldiskfs/lustre_quota_fmt.c index dd0ad3c..af6dad1 100644 --- a/lustre/ldiskfs/lustre_quota_fmt.c +++ b/lustre/ldiskfs/lustre_quota_fmt.c @@ -536,7 +536,8 @@ static int remove_tree(struct lustre_dquot *dquot, uint *blk, int depth) int i; ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(0); for (i = 0; i < LUSTRE_DQBLKSIZE && !buf[i]; i++); /* Block got empty? */ - if (i == LUSTRE_DQBLKSIZE) { + /* don't put the root block into free blk list! */ + if (i == LUSTRE_DQBLKSIZE && *blk != LUSTRE_DQTREEOFF) { put_free_dqblk(filp, info, buf, *blk); *blk = 0; } @@ -692,16 +693,10 @@ int lustre_commit_dquot(struct lustre_dquot *dquot) /* The block/inode usage in admin quotafile isn't the real usage * over all cluster, so keep the fake dquot entry on disk is * meaningless, just remove it */ -#ifndef QFMT_NO_DELETE if (test_bit(DQ_FAKE_B, &dquot->dq_flags)) rc = lustre_delete_dquot(dquot); - } - else { + else rc = lustre_write_dquot(dquot); - } -#else - rc = lustre_write_dquot(dquot); -#endif if (rc < 0) return rc; diff --git a/lustre/ldiskfs/quotafmt_test.c b/lustre/ldiskfs/quotafmt_test.c index b3c9e44..6c354bb 100644 --- a/lustre/ldiskfs/quotafmt_test.c +++ b/lustre/ldiskfs/quotafmt_test.c @@ -260,9 +260,6 @@ static int quotfmt_test_3(struct lustre_quota_info *lqi) int i = 0, rc = 0; ENTRY; -#ifdef QFMT_NO_DELETE - RETURN(0); -#endif dquot = get_rand_dquot(lqi); if (dquot == NULL) RETURN(-ENOMEM); @@ -283,6 +280,7 @@ repeat: CERROR("read dquot failed! (rc:%d)\n", rc); GOTO(out, rc); } + if (!dquot->dq_off || test_bit(DQ_FAKE_B, &dquot->dq_flags)) { CERROR("the dquot isn't committed\n"); GOTO(out, rc = -EINVAL); @@ -315,8 +313,6 @@ repeat: if (++i < 2) goto repeat; - print_quota_info(lqi); - out: put_rand_dquot(dquot); RETURN(rc); diff --git a/lustre/mds/handler.c b/lustre/mds/handler.c index 1f8efb6..9537e48 100644 --- a/lustre/mds/handler.c +++ b/lustre/mds/handler.c @@ -1047,16 +1047,16 @@ static int mds_quotacheck_thread(void *data) struct obd_quotactl *oqctl; struct obd_run_ctxt saved; int rc; - + lock_kernel(); ptlrpc_daemonize(); - + SIGNAL_MASK_LOCK(current, flags); sigfillset(¤t->blocked); RECALC_SIGPENDING; SIGNAL_MASK_UNLOCK(current, flags); - THREAD_NAME(current->comm, sizeof(current->comm) - 1, "%s", "quotacheck"); + THREAD_NAME(current->comm, sizeof(current->comm) - 1, "quotacheck"); unlock_kernel(); complete(&qchki->qi_starting); @@ -1730,6 +1730,15 @@ static int mds_setup(struct obd_device *obd, obd_count len, void *buf) "mds_ldlm_client", &obd->obd_ldlm_client); obd->obd_replayable = 1; + /* initialize quota master and quota context */ + sema_init(&mds->mds_quota_info.qi_sem, 1); + rc = qctxt_init(&mds->mds_quota_ctxt, mds->mds_sb, dqacq_handler); + if (rc) { + CERROR("initialize quota context failed! (rc:%d)\n", rc); + qctxt_cleanup(&mds->mds_quota_ctxt, 0); + GOTO(err_fs, rc); + } + rc = mds_postsetup(obd); if (rc) GOTO(err_fs, rc); @@ -1761,15 +1770,6 @@ static int mds_setup(struct obd_device *obd, obd_count len, void *buf) ping_evictor_start(); - sema_init(&mds->mds_quota_info.qi_sem, 1); - rc = qctxt_init(&mds->mds_quota_ctxt, mds->mds_sb, dqacq_handler); - if (rc) { - CERROR("initialize quota context failed! (rc:%d)\n", rc); - qctxt_cleanup(&mds->mds_quota_ctxt, 0); - GOTO(err_fs, rc); - } - - RETURN(0); err_fs: diff --git a/lustre/mds/mds_open.c b/lustre/mds/mds_open.c index 54af699..5037d3d 100644 --- a/lustre/mds/mds_open.c +++ b/lustre/mds/mds_open.c @@ -367,6 +367,9 @@ static int mds_create_objects(struct ptlrpc_request *req, int offset, RETURN(0); } + LASSERT(ret_logcookies); + LASSERT(setattr_async_flag); + if (OBD_FAIL_CHECK_ONCE(OBD_FAIL_MDS_ALLOC_OBDO)) GOTO(out_ids, rc = -ENOMEM); @@ -481,6 +484,7 @@ static int mds_create_objects(struct ptlrpc_request *req, int offset, if (logcookies == NULL) GOTO(out_oa, rc = -ENOMEM); *ret_logcookies = logcookies; + if (mds_log_op_setattr(obd, inode, lmm, lmm_size, logcookies, mds->mds_max_cookiesize) <= 0) { OBD_FREE(logcookies, mds->mds_max_cookiesize); @@ -731,16 +735,11 @@ static int mds_open_by_fid(struct ptlrpc_request *req, struct ll_fid *fid, struct mds_body *body, int flags, struct mds_update_record *rec,struct ldlm_reply *rep) { - struct obd_device *obd = req->rq_export->exp_obd; struct mds_obd *mds = mds_req2mds(req); struct dentry *dchild; char fidname[LL_FID_NAMELEN]; int fidlen = 0, rc; void *handle = NULL; - struct llog_cookie *logcookies = NULL; - struct lov_mds_md *lmm = NULL; - int lmm_size = 0; - int setattr_async_flag = 0; ENTRY; fidlen = ll_fid2str(fidname, fid->id, fid->generation); @@ -776,16 +775,9 @@ static int mds_open_by_fid(struct ptlrpc_request *req, struct ll_fid *fid, open: rc = mds_finish_open(req, dchild, body, flags, &handle, rec, rep, - &logcookies, &setattr_async_flag); + NULL, NULL); rc = mds_finish_transno(mds, dchild ? dchild->d_inode : NULL, handle, req, rc, rep ? rep->lock_policy_res1 : 0); - /* do mds to ost setattr for new created objects */ - if (rc == 0 && setattr_async_flag) { - lmm = lustre_msg_buf(req->rq_repmsg, 2, 0); - lmm_size = req->rq_repmsg->buflens[2]; - rc = mds_osc_setattr_async(obd, dchild->d_inode, lmm, lmm_size, - logcookies); - } /* XXX what do we do here if mds_finish_transno itself failed? */ l_dput(dchild); @@ -1103,6 +1095,8 @@ int mds_open(struct mds_update_record *rec, int offset, mds_osc_setattr_async(obd, dchild->d_inode, lmm, lmm_size, logcookies); } + if (logcookies) + OBD_FREE(logcookies, mds->mds_max_cookiesize); cleanup_no_trans: switch (cleanup_phase) { @@ -1132,7 +1126,7 @@ int mds_open(struct mds_update_record *rec, int offset, else ptlrpc_save_lock (req, &parent_lockh, parent_mode); } - + /* trigger dqacq on the owner of child and parent */ mds_adjust_qunit(obd, current->fsuid, current->fsgid, parent_uid, parent_gid, rc); diff --git a/lustre/mds/mds_reint.c b/lustre/mds/mds_reint.c index ea46f39..b468231 100644 --- a/lustre/mds/mds_reint.c +++ b/lustre/mds/mds_reint.c @@ -376,11 +376,11 @@ int mds_osc_setattr_async(struct obd_device *obd, struct inode *inode, struct lov_stripe_md *lsm = NULL; struct obd_trans_info oti = { 0 }; struct obdo *oa = NULL; - int cleanup_phase = 0, rc = 0; + int rc; ENTRY; if (OBD_FAIL_CHECK(OBD_FAIL_MDS_OST_SETATTR)) - GOTO(cleanup, rc); + RETURN(0); /* first get memory EA */ oa = obdo_alloc(); @@ -389,14 +389,12 @@ int mds_osc_setattr_async(struct obd_device *obd, struct inode *inode, LASSERT(lmm); - cleanup_phase = 1; rc = obd_unpackmd(mds->mds_osc_exp, &lsm, lmm, lmm_size); if (rc < 0) { CERROR("Error unpack md %p\n", lmm); - GOTO(cleanup, rc); + GOTO(out, rc); } - cleanup_phase = 2; /* then fill oa */ oa->o_id = lsm->lsm_object_id; oa->o_uid = inode->i_uid; @@ -410,19 +408,12 @@ int mds_osc_setattr_async(struct obd_device *obd, struct inode *inode, /* do setattr from mds to ost asynchronously */ rc = obd_setattr_async(mds->mds_osc_exp, oa, lsm, &oti); if (rc) - CDEBUG(D_INODE, "mds to ost setattr objid 0x"LPX64" on ost error " - "%d\n", lsm->lsm_object_id, rc); -cleanup: - switch(cleanup_phase) { - case 2: - obd_free_memmd(mds->mds_osc_exp, &lsm); - case 1: - obdo_free(oa); - case 0: - if (logcookies) - OBD_FREE(logcookies, mds->mds_max_cookiesize); - } + CDEBUG(D_INODE, "mds to ost setattr objid 0x"LPX64 + " on ost error %d\n", lsm->lsm_object_id, rc); + obd_free_memmd(mds->mds_osc_exp, &lsm); + out: + obdo_free(oa); RETURN(rc); } @@ -529,6 +520,7 @@ static int mds_reint_setattr(struct mds_update_record *rec, int offset, OBD_ALLOC(logcookies, mds->mds_max_cookiesize); if (logcookies == NULL) GOTO(cleanup, rc = -ENOMEM); + if (mds_log_op_setattr(obd, inode, lmm, lmm_size, logcookies, mds->mds_max_cookiesize) <= 0) { @@ -613,6 +605,8 @@ static int mds_reint_setattr(struct mds_update_record *rec, int offset, switch (cleanup_phase) { case 2: OBD_FREE(lmm, mds->mds_max_mdsize); + if (logcookies) + OBD_FREE(logcookies, mds->mds_max_cookiesize); case 1: if ((S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)) && rec->ur_eadata != NULL) diff --git a/lustre/mds/quota_context.c b/lustre/mds/quota_context.c index c0bda90..d601edb 100644 --- a/lustre/mds/quota_context.c +++ b/lustre/mds/quota_context.c @@ -442,8 +442,10 @@ schedule_dqacq(struct obd_device *obd, /* build dqacq/dqrel request */ LASSERT(qctxt->lqc_import); req = ptlrpc_prep_req(qctxt->lqc_import, opc, 1, &size, NULL); - if (!req) + if (!req) { + dqacq_completion(obd, qctxt, qdata, -ENOMEM, opc); RETURN(-ENOMEM); + } reqdata = lustre_msg_buf(req->rq_reqmsg, 0, sizeof(*reqdata)); memcpy(reqdata, qdata, sizeof(*reqdata)); @@ -470,7 +472,7 @@ wait_completion: if (qw.qw_rc == 0) rc = -EAGAIN; - QDATA_DEBUG(p, "wait dqacq done. (rc:%d)\n", qw.qw_rc); + CDEBUG(D_QUOTA, "wait dqacq done. (rc:%d)\n", qw.qw_rc); } RETURN(rc); } diff --git a/lustre/mds/quota_master.c b/lustre/mds/quota_master.c index e7ca633..d1c8797 100644 --- a/lustre/mds/quota_master.c +++ b/lustre/mds/quota_master.c @@ -229,10 +229,15 @@ int dqacq_handler(struct obd_device *obd, struct qunit_data *qdata, int opc) struct lustre_quota_info *info = &mds->mds_quota_info; struct lustre_dquot *dquot = NULL; __u64 *usage = NULL; - __u32 *limit = NULL; + __u32 hlimit = 0, slimit = 0; + time_t *time = NULL; + unsigned int grace = 0; int rc = 0; ENTRY; + /* slaves never acquires qunit for user root */ + LASSERT(qdata->qd_id || qdata->qd_type == GRPQUOTA); + dquot = lustre_dqget(obd, info, qdata->qd_id, qdata->qd_type); if (IS_ERR(dquot)) RETURN(PTR_ERR(dquot)); @@ -244,27 +249,48 @@ int dqacq_handler(struct obd_device *obd, struct qunit_data *qdata, int opc) down(&dquot->dq_sem); if (qdata->qd_isblk) { + grace = info->qi_info[qdata->qd_type].dqi_bgrace; usage = &dquot->dq_dqb.dqb_curspace; - limit = &dquot->dq_dqb.dqb_bhardlimit; + hlimit = dquot->dq_dqb.dqb_bhardlimit; + slimit = dquot->dq_dqb.dqb_bsoftlimit; + time = &dquot->dq_dqb.dqb_btime; } else { + grace = info->qi_info[qdata->qd_type].dqi_igrace; usage = (__u64 *) & dquot->dq_dqb.dqb_curinodes; - limit = &dquot->dq_dqb.dqb_ihardlimit; - } + hlimit = dquot->dq_dqb.dqb_ihardlimit; + slimit = dquot->dq_dqb.dqb_isoftlimit; + time = &dquot->dq_dqb.dqb_itime; + } /* if the quota limit in admin quotafile is zero, we just inform * slave to clear quota limit with zero qd_count */ - if (*limit == 0) { + if (hlimit == 0 && slimit == 0) { qdata->qd_count = 0; GOTO(out, rc); } + if (opc == QUOTA_DQACQ) { - if (QUSG(*usage + qdata->qd_count, qdata->qd_isblk) > *limit) + if (hlimit && + QUSG(*usage + qdata->qd_count, qdata->qd_isblk) > hlimit) GOTO(out, rc = -EDQUOT); - else - *usage += qdata->qd_count; + + if (slimit && + QUSG(*usage + qdata->qd_count, qdata->qd_isblk) > slimit) { + if (*time && CURRENT_SECONDS >= *time) + GOTO(out, rc = -EDQUOT); + else if (!*time) + *time = CURRENT_SECONDS + grace; + } + + *usage += qdata->qd_count; + } else if (opc == QUOTA_DQREL) { LASSERT(*usage - qdata->qd_count >= 0); *usage -= qdata->qd_count; + + /* (usage <= soft limit) but not (usage < soft limit) */ + if (!slimit || QUSG(*usage, qdata->qd_isblk) <= slimit) + *time = 0; } else { LBUG(); } @@ -517,7 +543,7 @@ static int mds_init_slave_ilimits(struct obd_device *obd, ENTRY; /* if we are going to set zero limit, needn't init slaves */ - if (!oqctl->qc_dqblk.dqb_ihardlimit) + if (!oqctl->qc_dqblk.dqb_ihardlimit && !oqctl->qc_dqblk.dqb_isoftlimit) RETURN(0); OBD_ALLOC(ioqc, sizeof(*ioqc)); @@ -562,7 +588,7 @@ static int mds_init_slave_blimits(struct obd_device *obd, ENTRY; /* if we are going to set zero limit, needn't init slaves */ - if (!oqctl->qc_dqblk.dqb_bhardlimit) + if (!oqctl->qc_dqblk.dqb_bhardlimit && !oqctl->qc_dqblk.dqb_bsoftlimit) RETURN(0); OBD_ALLOC(ioqc, sizeof(*ioqc)); @@ -634,7 +660,8 @@ int mds_set_dqblk(struct obd_device *obd, struct obd_quotactl *oqctl) dquot->dq_dqb.dqb_bhardlimit = dqblk->dqb_bhardlimit; dquot->dq_dqb.dqb_bsoftlimit = dqblk->dqb_bsoftlimit; /* clear usage (limit pool) */ - if (dquot->dq_dqb.dqb_bhardlimit == 0) + if (!dquot->dq_dqb.dqb_bhardlimit && + !dquot->dq_dqb.dqb_bsoftlimit) dquot->dq_dqb.dqb_curspace = 0; } @@ -642,7 +669,8 @@ int mds_set_dqblk(struct obd_device *obd, struct obd_quotactl *oqctl) dquot->dq_dqb.dqb_ihardlimit = dqblk->dqb_ihardlimit; dquot->dq_dqb.dqb_isoftlimit = dqblk->dqb_isoftlimit; /* clear usage (limit pool) */ - if (dquot->dq_dqb.dqb_ihardlimit == 0) + if (!dquot->dq_dqb.dqb_ihardlimit && + !dquot->dq_dqb.dqb_isoftlimit) dquot->dq_dqb.dqb_curinodes = 0; } @@ -660,7 +688,7 @@ int mds_set_dqblk(struct obd_device *obd, struct obd_quotactl *oqctl) if (rc) GOTO(out, rc); - if (dqblk->dqb_valid & QIF_ILIMITS && !ihardlimit) { + if (dqblk->dqb_valid & QIF_ILIMITS && !(ihardlimit || isoftlimit)) { rc = mds_init_slave_ilimits(obd, oqctl); if (rc) { CERROR("init slave ilimits failed! (rc:%d)\n", rc); @@ -668,7 +696,7 @@ int mds_set_dqblk(struct obd_device *obd, struct obd_quotactl *oqctl) } } - if (dqblk->dqb_valid & QIF_BLIMITS && !bhardlimit) { + if (dqblk->dqb_valid & QIF_BLIMITS && !(bhardlimit || bsoftlimit)) { rc = mds_init_slave_blimits(obd, oqctl); if (rc) { CERROR("init slave blimits failed! (rc:%d)\n", rc); diff --git a/lustre/tests/quota_sanity.sh b/lustre/tests/quota_sanity.sh index 9261668..59f1b72 100644 --- a/lustre/tests/quota_sanity.sh +++ b/lustre/tests/quota_sanity.sh @@ -13,10 +13,12 @@ USER="quota_usr" TSTID=${TSTID:-60000} RUNAS=${RUNAS:-"runas -u $TSTID"} BLK_SZ=1024 -BUNIT_SZ=10 # 10 quota blocks -BTUNE_SZ=5 # 5 quota blocks +BUNIT_SZ=1000 # 1000 quota blocks +BTUNE_SZ=500 # 500 quota blocks IUNIT_SZ=10 # 10 files ITUNE_SZ=5 # 5 files +MAX_DQ_TIME=604800 +MAX_IQ_TIME=604800 MOUNT="`cat /proc/mounts | grep "lustre" | awk '{print $2}'`" if [ -z "$MOUNT" ]; then @@ -26,37 +28,46 @@ fi OSTCOUNT=`cat /proc/fs/lustre/lov/*/activeobd | head -n 1` TSTDIR="$MOUNT/quota_dir" -# set_blk_tunables(bunit_sz, btune_sz) -set_blk_tunables() { - # set bunit and btune size on all obdfilters +# set_blk_tunables(btune_sz) +set_blk_tunesz() { + # set btune size on all obdfilters for i in `ls /proc/fs/lustre/obdfilter/*/quota_btune_sz`; do - echo $(($2 * $BLK_SZ)) > $i + echo $(($1 * $BLK_SZ)) > $i + done + # set btune size on mds + for i in `ls /proc/fs/lustre/mds/mds*/quota_btune_sz`; do + echo $(($1 * $BLK_SZ)) > $i done +} + +# se_blk_unitsz(bunit_sz) +set_blk_unitsz() { for i in `ls /proc/fs/lustre/obdfilter/*/quota_bunit_sz`; do echo $(($1 * $BLK_SZ)) > $i - done; - # set bunit and btune size on mds - for i in `ls /proc/fs/lustre/mds/mds*/quota_btune_sz`; do - echo $(($2 * $BLK_SZ)) > $i done for i in `ls /proc/fs/lustre/mds/mds*/quota_bunit_sz`; do echo $(($1 * $BLK_SZ)) > $i done } -# set_file_tunables(iunit_sz, itune_sz) -set_file_tunables() { +# set_file_tunesz(itune_sz) +set_file_tunesz() { # set iunit and itune size on all obdfilters for i in `ls /proc/fs/lustre/obdfilter/*/quota_itune_sz`; do - echo $2 > $i - done - for i in `ls /proc/fs/lustre/obdfilter/*/quota_iunit_sz`; do echo $1 > $i - done; + done # set iunit and itune size on mds for i in `ls /proc/fs/lustre/mds/mds*/quota_itune_sz`; do - echo $2 > $i + echo $1 > $i done + + +} +# set_file_unitsz(iunit_sz) +set_file_unitsz() { + for i in `ls /proc/fs/lustre/obdfilter/*/quota_iunit_sz`; do + echo $1 > $i + done; for i in `ls /proc/fs/lustre/mds/mds*/quota_iunit_sz`; do echo $1 > $i done @@ -77,27 +88,29 @@ prepare_test() { fi RUNAS="runas -u $TSTID" + # set block tunables - - set_blk_tunables $BUNIT_SZ $BTUNE_SZ + set_blk_tunesz $BTUNE_SZ + set_blk_unitsz $BUNIT_SZ # set file tunaables - set_file_tunables $IUNIT_SZ $ITUNE_SZ + set_file_tunesz $ITUNE_SZ + set_file_unitsz $IUNIT_SZ [ -d $TSTDIR ] || mkdir $TSTDIR chmod 777 $TSTDIR } -cleanup_test() { - # delete test user and group - userdel "$USER" - groupdel "$USER" - +cleanup_test() { # restore block tunables to default size - set_blk_tunables $((1024 * 100)) $((1024 * 50)) + set_blk_unitsz $((1024 * 100)) + set_blk_tunesz $((1024 * 50)) # restore file tunables to default size - set_file_tunables 5000 2500 + set_file_unitsz 5000 + set_file_tunesz 2500 rm -fr $TSTDIR + # delete test user and group + userdel "$USER" } # set quota @@ -105,6 +118,9 @@ test_1() { echo "== Enable quota" $LFS quotaoff -ug $MOUNT $LFS quotacheck -ug $MOUNT + + $LFS setquota -u $USER 0 0 0 0 $MOUNT + $LFS setquota -g $USER 0 0 0 0 $MOUNT return 0 } @@ -123,7 +139,8 @@ test_2() { $RUNAS dd if=/dev/zero of=$TESTFILE bs=$BLK_SZ count=$(($LIMIT/2)) > /dev/null 2>&1 || error "(usr) write failure, but expect success" echo " Done" echo " Write out of block quota ..." - $RUNAS dd if=/dev/zero of=$TESTFILE bs=$BLK_SZ count=$(($LIMIT/2)) seek=$(($LIMIT/2)) > /dev/null 2>&1 + # this time maybe cache write, ignore it's failure + $RUNAS dd if=/dev/zero of=$TESTFILE bs=$BLK_SZ count=$(($LIMIT/2)) seek=$(($LIMIT/2)) > /dev/null 2>&1 || echo " " > /dev/null # flush cache, ensure noquota flag is setted on client sync; sleep 1; sync; $RUNAS dd if=/dev/zero of=$TESTFILE bs=$BLK_SZ count=$BUNIT_SZ seek=$LIMIT > /dev/null 2>&1 && error "(usr) write success, but expect EDQUOT" @@ -142,7 +159,8 @@ test_2() { $RUNAS dd if=/dev/zero of=$TESTFILE bs=$BLK_SZ count=$(($LIMIT/2)) > /dev/null 2>&1 || error "(grp) write failure, but expect success" echo " Done" echo " Write out of block quota ..." - $RUNAS dd if=/dev/zero of=$TESTFILE bs=$BLK_SZ count=$(($LIMIT/2)) seek=$(($LIMIT/2)) > /dev/null 2>&1 + # this time maybe cache write, ignore it's failure + $RUNAS dd if=/dev/zero of=$TESTFILE bs=$BLK_SZ count=$(($LIMIT/2)) seek=$(($LIMIT/2)) > /dev/null 2>&1 || echo " " > /dev/null sync; sleep 1; sync; $RUNAS dd if=/dev/zero of=$TESTFILE bs=$BLK_SZ count=$BUNIT_SZ seek=$LIMIT > /dev/null 2>&1 && error "(grp) write success, but expect EDQUOT" echo " EDQUOT" @@ -197,17 +215,135 @@ test_3() { return 0 } +test_block_soft() { + TESTFILE=$1 + GRACE=$2 + BS=$(($BUNIT_SZ * $BLK_SZ)) + + echo " Write to exceed soft limit" + $RUNAS dd if=/dev/zero of=$TESTFILE bs=$BLK_SZ count=$BUNIT_SZ >/dev/null 2>&1 || error "write failure, but expect success" + sync; sleep 1; sync; + + echo " Write before timer goes off" + $RUNAS dd if=/dev/zero of=$TESTFILE bs=$BLK_SZ count=$BUNIT_SZ seek=$BUNIT_SZ >/dev/null 2>&1 || error "write failure, but expect success" + sync; sleep 1; sync; + echo " Done" + + echo " Sleep $GRACE seconds ..." + sleep $GRACE + + echo " Write after timer goes off" + # maybe cache write, ignore. + $RUNAS dd if=/dev/zero of=$TESTFILE bs=$BLK_SZ count=$BUNIT_SZ seek=$(($BUNIT_SZ * 2)) >/dev/null 2>&1 || echo " " > /dev/null + sync; sleep 1; sync; + $RUNAS dd if=/dev/zero of=$TESTFILE bs=$BLK_SZ count=1 seek=$(($BUNIT_SZ * 3)) >/dev/null 2>&1 && error "write success, but expect EDQUOT" + echo " EDQUOT" + + echo " Unlink file to stop timer" + rm -f $TESTFILE + echo " Done" + + echo " Write ..." + $RUNAS dd if=/dev/zero of=$TESTFILE bs=$BLK_SZ count=$BUNIT_SZ >/dev/null 2>&1 || error "write failure, but expect success" + echo " Done" + + # cleanup + rm -f $TESTFILE +} + # block soft limit (start timer, timer goes off, stop timer) test_4() { echo "== Block soft limit" - echo " ** skipped" + LIMIT=$(( $BUNIT_SZ * $(($OSTCOUNT + 1)) )) # 1 bunits each sever + TESTFILE="$TSTDIR/quota_tst40" + GRACE=10 + + echo " User quota (soft limit: $LIMIT bytes grace: $GRACE seconds)" + $LFS setquota -t -u $GRACE $MAX_IQ_TIME $MOUNT + $LFS setquota -u $USER $LIMIT 0 0 0 $MOUNT + + test_block_soft $TESTFILE $GRACE + $LFS setquota -u $USER 0 0 0 0 $MOUNT + + echo " Group quota (soft limit: $LIMIT bytes grace: $GRACE seconds)" + $LFS setquota -t -g $GRACE $MAX_IQ_TIME $MOUNT + $LFS setquota -g $USER $LIMIT 0 0 0 $MOUNT + TESTFILE="$TSTDIR/quota_tst41" + + test_block_soft $TESTFILE $GRACE + $LFS setquota -g $USER 0 0 0 0 $MOUNT + return 0 } +test_file_soft() { + TESTFILE=$1 + LIMIT=$2 + GRACE=$3 + + echo " Create files to exceed soft limit" + for i in `seq $LIMIT`; do + $RUNAS touch ${TESTFILE}_$i >/dev/null 2>&1 || error "touch failure, but expect success" + done + echo " Done" + + echo " Create file before timer goes off" + $RUNAS touch ${TESTFILE}_before >/dev/null 2>&1 || error "touch before timer goes off failure, but expect success" + echo " Done" + + echo " Sleep $GRACE seconds ..." + sleep $GRACE + + echo " Create file after timer goes off" + for i in `seq $(($IUNIT_SZ - 1))`; do + $RUNAS touch ${TESTFILE}_after_$i >/dev/null 2>&1 || error "touch ${TESTFILE}_after_$i failure, but expect success" + done + $RUNAS touch ${TESTFILE}_after >/dev/null 2>&1 && error "touch after timer goes off success, but expect EDQUOT" + echo " EDQUOT" + + echo " Unlink files to stop timer" + for i in `seq $LIMIT`; do + rm -f ${TESTFILE}_$i >/dev/null 2>&1 || error "rm ${TESTFILE}_$i failure" + done + rm -f ${TESTFILE}_before + for i in `seq $(($IUNIT_SZ - 1))`; do + rm -f ${TESTFILE}_after_$i >/dev/null 2>&1 || error "rm ${TESTFILE}_after_$i failure" + done + echo " Done" + + echo " Create file" + $RUNAS touch ${TESTFILE}_xxx >/dev/null 2>&1 || error "touch after timer stop failure, but expect success" + echo " Done" + + # cleanup + rm -f ${TESTFILE}_xxx +} + # file soft limit (start timer, timer goes off, stop timer) test_5() { echo "== File soft limit" - echo " ** skipped" + LIMIT=$(($IUNIT_SZ * 10)) # 10 iunits on mds + TESTFILE="$TSTDIR/quota_tst50" + GRACE=5 + + echo " User quota (soft limit: $LIMIT files grace: $GRACE seconds)" + $LFS setquota -t -u $MAX_DQ_TIME $GRACE $MOUNT + $LFS setquota -u $USER 0 0 $LIMIT 0 $MOUNT + + test_file_soft $TESTFILE $LIMIT $GRACE + $LFS setquota -u $USER 0 0 0 0 $MOUNT + + echo " Group quota (soft limit: $LIMIT files grace: $GRACE seconds)" + $LFS setquota -t -g $MAX_DQ_TIME $GRACE $MOUNT + $LFS setquota -g $USER 0 0 $LIMIT 0 $MOUNT + TESTFILE="$TSTDIR/quota_tst51" + + test_file_soft $TESTFILE $LIMIT $GRACE + $LFS setquota -g $USER 0 0 0 0 $MOUNT + + # cleanup + $LFS setquota -t -u $MAX_DQ_TIME $MAX_IQ_TIME $MOUNT + $LFS setquota -t -g $MAX_DQ_TIME $MAX_IQ_TIME $MOUNT return 0 } @@ -270,8 +406,8 @@ test_7() { $RUNAS dd if=/dev/zero of=$FILEB bs=$BLK_SZ seek=$LIMIT count=$BUNIT_SZ >/dev/null 2>&1 && error "write fileb success, but expect EDQUOT" sync; sleep 1; sync; echo " Write to OST0 return EDQUOT" - # this write of OST0 is cache write, will success - $RUNAS dd if=/dev/zero of=$FILEA bs=$BLK_SZ count=$(($BUNIT_SZ * 2)) >/dev/null 2>&1 || error "write filea failure, but expect success" + # this write maybe cache write, ignore it's failure + $RUNAS dd if=/dev/zero of=$FILEA bs=$BLK_SZ count=$(($BUNIT_SZ * 2)) >/dev/null 2>&1 || echo " " > /dev/null sync; sleep 1; sync; $RUNAS dd if=/dev/zero of=$FILEA bs=$BLK_SZ count=$(($BUNIT_SZ * 2)) seek=$(($BUNIT_SZ *2)) >/dev/null 2>&1 && error "write filea success, but expect EDQUOT" echo " EDQUOT"