diff --git a/lustre/ChangeLog b/lustre/ChangeLog index a100d5a70adbc417ccf4f1aca32bb8e12ac2c899..3d13564f9fdb96598fa3946d5af8a06cf0899271 100644 --- a/lustre/ChangeLog +++ b/lustre/ChangeLog @@ -341,6 +341,13 @@ Description: add quota statistics Details : 1. sort out quota proc entries and proc code. 2. add quota statistics +Severity : normal +Frequncy : often +Bugzilla : 16125 +Description: quotas are not honored with O_DIRECT +Details : all writes with the flag O_DIRECT will use grants which leads to + this problem. Now using OBD_BRW_SYNC to guard this. + ------------------------------------------------------------------------------- diff --git a/lustre/llite/rw26.c b/lustre/llite/rw26.c index 5f57c2e83f0ff9b3eaaab5445e93099d4acefc24..0a92f298c454a64eedaf949a3dbdc461e4520be7 100644 --- a/lustre/llite/rw26.c +++ b/lustre/llite/rw26.c @@ -177,7 +177,7 @@ static ssize_t ll_direct_IO_26_seg(int rw, struct inode *inode, /* To the end of the page, or the length, whatever is less */ pga[i].count = min_t(int, CFS_PAGE_SIZE -(file_offset & ~CFS_PAGE_MASK), length); - pga[i].flag = 0; + pga[i].flag = OBD_BRW_SYNC; if (rw == READ) POISON_PAGE(pages[i], 0x0d); } diff --git a/lustre/obdfilter/filter_io_26.c b/lustre/obdfilter/filter_io_26.c index c57ad10e4e32e0e7156edd68f69e68a9c46c2465..8a42366822f49fe7b847b558c08b23db71f611f1 100644 --- a/lustre/obdfilter/filter_io_26.c +++ b/lustre/obdfilter/filter_io_26.c @@ -697,10 +697,11 @@ int filter_commitrw_write(struct obd_export *exp, struct obdo *oa, if (this_size > iattr.ia_size) iattr.ia_size = this_size; - /* if one page is a write-back page from client cache, or it's - * written by root, then mark the whole io request as ignore - * quota request */ - if (lnb->flags & (OBD_BRW_FROM_GRANT | OBD_BRW_NOQUOTA)) + /* if one page is a write-back page from client cache and + * not from direct_io, or it's written by root, then mark + * the whole io request as ignore quota request */ + if (lnb->flags & OBD_BRW_NOQUOTA || + (lnb->flags & (OBD_BRW_FROM_GRANT | OBD_BRW_SYNC)) == OBD_BRW_FROM_GRANT) iobuf->dr_ignore_quota = 1; } diff --git a/lustre/tests/sanity-quota.sh b/lustre/tests/sanity-quota.sh index 224b03a419f17ef83e1f744f962624aa755079ba..810f7aa8d66c2812092cedaf648afe9f867e49b2 100644 --- a/lustre/tests/sanity-quota.sh +++ b/lustre/tests/sanity-quota.sh @@ -46,6 +46,7 @@ LUSTRE=${LUSTRE:-`dirname $0`/..} . $LUSTRE/tests/test-framework.sh init_test_env $@ . ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh} +DIRECTIO=${DIRECTIO:-$LUSTRE/tests/directio} [ "$SLOW" = "no" ] && EXCEPT_SLOW="9 10 11 21" @@ -1660,6 +1661,58 @@ test_22() { } run_test_with_stat 22 "test if quota_type saved as permanent parameter ====" +test_23_sub() { + mkdir -p $DIR/$tdir + chmod 0777 $DIR/$tdir + TESTFILE="$DIR/$tdir/$tfile-0" + local bs_unit=$((1024*1024)) + LIMIT=$1 + + wait_delete_completed + + # test for user + log " User quota (limit: $LIMIT kbytes)" + $LFS setquota -u $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $DIR + sleep 3 + $SHOW_QUOTA_USER + + $LFS setstripe $TESTFILE -c 1 + chown $TSTUSR.$TSTUSR $TESTFILE + + log " Step1: trigger quota with 0_DIRECT" + log " Write half of file" + $RUNAS $DIRECTIO write $TESTFILE 0 $(($LIMIT/1024/2)) $bs_unit || error "(usr) write failure, but expect success" + log " Write out of block quota ..." + $RUNAS $DIRECTIO write $TESTFILE $(($LIMIT/1024/2)) $(($LIMIT/1024/2)) $bs_unit && error "(usr) write success, but expect EDQUOT" + log " Step1: done" + + log " Step2: rewrite should succeed" + $RUNAS $DIRECTIO write $TESTFILE $(($LIMIT/1024/2)) 1 $bs_unit 2>&1 || error "(usr) write failure, but expect success" + log " Step2: done" + + rm -f $TESTFILE + wait_delete_completed + OST0_UUID=`do_facet ost1 $LCTL dl | grep -m1 obdfilter | awk '{print $((NF-1))}'` + OST0_QUOTA_USED=`$LFS quota -o $OST0_UUID -u $TSTUSR $DIR | awk '/^.*[[:digit:]+][[:space:]+]/ { print $1 }'` + echo $OST0_QUOTA_USED + [ $OST0_QUOTA_USED -ne 0 ] && \ + ($SHOW_QUOTA_USER; error "quota deleted isn't released") + $SHOW_QUOTA_USER + $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR + +} + +test_23() { + log "run for 10MB test file" + test_23_sub 10240 #10MB + + OST0_MIN=120000 + check_whether_skip && return 0 + log "run for 100MB test file" + test_23_sub 102400 #100MB +} +run_test_with_stat 23 "run for fixing bug16125 ===========" + # turn off quota test_99() {