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.
#include <linux/quota.h>
#include <linux/lustre_idl.h>
-/* 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
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;
}
/* 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;
int i = 0, rc = 0;
ENTRY;
-#ifdef QFMT_NO_DELETE
- RETURN(0);
-#endif
dquot = get_rand_dquot(lqi);
if (dquot == NULL)
RETURN(-ENOMEM);
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);
if (++i < 2)
goto repeat;
- print_quota_info(lqi);
-
out:
put_rand_dquot(dquot);
RETURN(rc);
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);
"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);
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:
RETURN(0);
}
+ LASSERT(ret_logcookies);
+ LASSERT(setattr_async_flag);
+
if (OBD_FAIL_CHECK_ONCE(OBD_FAIL_MDS_ALLOC_OBDO))
GOTO(out_ids, rc = -ENOMEM);
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);
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);
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);
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) {
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);
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();
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;
/* 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);
}
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) {
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)
/* 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));
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);
}
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));
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();
}
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));
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));
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;
}
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;
}
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);
}
}
- 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);
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
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
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
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
}
$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"
$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"
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
}
$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"