Re: [PATCH] test Q_GETNEXTQUOTA

[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]



Ignore that, sorry.  I see Dave committed it.

> On Feb 18, 2016, at 11:35 PM, Eric Sandeen <sandeen@xxxxxxxxxxx> wrote:
> 
> Ping?
> 
>> On Jan 21, 2016, at 6:02 PM, Eric Sandeen <sandeen@xxxxxxxxxxx> wrote:
>> 
>> The new Q_GETNEXTQUOTA quotactl (not yet merged) is designed
>> to take an ID as input ala Q_GETQUOTA, and return the quota
>> for the next active ID >= the input ID.  This lets us quickly
>> iterate over all existing quotas by leveraging the kernel's
>> knowledge of which quotas are allocated and active.
>> 
>> The test contains a new helper binary, test-nextquota, which
>> tests both the "vfs" and "xfs" versions of the quotactl.
>> It accepts an ID, and outputs the returned ID, ihard, and
>> isoft values for that quota.  It doesn't return block information
>> simply because that can vary depending on fs, block size, etc,
>> and we want something very consistent as output, for verifiation.
>> 
>> The test harness sets quotas for 100 random IDs, remounts,
>> and uses these quotactls to iterate over all the IDs we set,
>> using the test binary, making sure we get back what we expect.
>> 
>> Not the prettiest thing, but it works!
>> 
>> Signed-off-by: Eric Sandeen <sandeen@xxxxxxxxxx>
>> ---
>> 
>> 
>> diff --git a/src/Makefile b/src/Makefile
>> index 4781736..48e6765 100644
>> --- a/src/Makefile
>> +++ b/src/Makefile
>> @@ -19,7 +19,7 @@ LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \
>>   bulkstat_unlink_test_modified t_dir_offset t_futimens t_immutable \
>>   stale_handle pwrite_mmap_blocked t_dir_offset2 seek_sanity_test \
>>   seek_copy_test t_readdir_1 t_readdir_2 fsync-tester nsexec cloner \
>> -    renameat2 t_getcwd e4compact
>> +    renameat2 t_getcwd e4compact test-nextquota
>> 
>> SUBDIRS =
>> 
>> diff --git a/src/test-nextquota.c b/src/test-nextquota.c
>> new file mode 100644
>> index 0000000..a2bbad9
>> --- /dev/null
>> +++ b/src/test-nextquota.c
>> @@ -0,0 +1,163 @@
>> +/*
>> + * Copyright (c) 2016 Red Hat, Inc.
>> + * All Rights Reserved.
>> + *
>> + * This program is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU General Public License as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it would be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, write the Free Software Foundation,
>> + * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
>> + */
>> +#include <stdlib.h>
>> +#include <stdio.h>
>> +#include <string.h>
>> +#include <sys/quota.h>
>> +#include <sys/types.h>
>> +#include <xfs/xqm.h>
>> +
>> +/*
>> + * Exercise the Q_GETNEXTQUOTA and Q_XGETNEXTQUOTA quotactls.
>> + * Really only returns a bare minimum of quota information,
>> + * just enough to be sure we got a sane answer back.
>> + *
>> + * These quotactls take a quota ID as input, and return the
>> + * next active quota >= that ID.
>> + *
>> + * usage:
>> + *    test-nextquota [-v] -[u|g|p] -i id -d device
>> + */
>> +
>> +#ifndef PRJQUOTA
>> +#define PRJQUOTA 2
>> +#endif
>> +
>> +#ifndef Q_GETNEXTQUOTA
>> +#define Q_GETNEXTQUOTA 0x800009        /* get disk limits and usage >= ID */
>> +
>> +struct nextdqblk
>> +  {
>> +    u_int64_t dqb_bhardlimit;    /* absolute limit on disk quota blocks alloc */
>> +    u_int64_t dqb_bsoftlimit;    /* preferred limit on disk quota blocks */
>> +    u_int64_t dqb_curspace;    /* current quota block count */
>> +    u_int64_t dqb_ihardlimit;    /* maximum # allocated inodes */
>> +    u_int64_t dqb_isoftlimit;    /* preferred inode limit */
>> +    u_int64_t dqb_curinodes;    /* current # allocated inodes */
>> +    u_int64_t dqb_btime;    /* time limit for excessive disk use */
>> +    u_int64_t dqb_itime;    /* time limit for excessive files */
>> +    u_int32_t dqb_valid;    /* bitmask of QIF_* constants */
>> +    u_int32_t dqb_id;        /* id for this quota info*/
>> +  };
>> +#endif
>> +
>> +#ifndef Q_XGETNEXTQUOTA
>> +#define Q_XGETNEXTQUOTA XQM_CMD(9)
>> +#endif
>> +
>> +void usage(char *progname)
>> +{
>> +    printf("usage: %s [-v] -[u|g|p] -i id -d device\n", progname);
>> +    exit(1);
>> +}
>> +
>> +int main(int argc, char *argv[])
>> +{
>> +    int c;
>> +    int cmd;
>> +    int type = -1, typeflag = 0;
>> +    int verbose = 0;
>> +    uint id = 0, idflag = 0;
>> +    char *device = NULL;
>> +    struct nextdqblk dqb;
>> +    struct fs_disk_quota xqb;
>> +
>> +    while ((c = getopt(argc,argv,"ugpi:d:v")) != EOF) {
>> +        switch (c) {
>> +        case 'u':
>> +            type = USRQUOTA;
>> +            typeflag++;
>> +            break;
>> +        case 'g':
>> +            type = GRPQUOTA;
>> +            typeflag++;
>> +            break;
>> +        case 'p':
>> +            type = PRJQUOTA;
>> +            typeflag++;
>> +            break;
>> +        case 'i':
>> +            id = atoi(optarg);
>> +            idflag++;
>> +            break;
>> +        case 'd':
>> +            device = optarg;
>> +            break;
>> +        case 'v':
>> +            verbose++;
>> +            break;
>> +        default:
>> +            usage(argv[0]);
>> +        }
>> +    }
>> +
>> +    if (idflag == 0) {
>> +        printf("No id specified\n");
>> +        usage(argv[0]);
>> +    }
>> +    if (typeflag == 0) {
>> +        printf("No type specified\n");
>> +        usage(argv[0]);
>> +    }
>> +    if (typeflag > 1) {
>> +        printf("Multiple types specified\n");
>> +        usage(argv[0]);
>> +    }
>> +    if (device == NULL) {
>> +        printf("No device specified\n");
>> +        usage(argv[0]);
>> +    }
>> +
>> +    if (verbose)
>> +        printf("asking for quota type %d for id %u on %s\n", type, id, device);
>> +
>> +    memset(&dqb, 0, sizeof(struct nextdqblk));
>> +    memset(&xqb, 0, sizeof(struct fs_disk_quota));
>> +
>> +    if (verbose)
>> +        printf("====Q_GETNEXTQUOTA====\n");
>> +    cmd = QCMD(Q_GETNEXTQUOTA, type);
>> +    if (quotactl(cmd, device, id, (void *)&dqb) < 0) {
>> +        perror("Q_GETNEXTQUOTA");
>> +        return 1;
>> +    }
>> +
>> +    /*
>> +     * We only print id and inode limits because
>> +     * block count varies depending on fs block size, etc;
>> +     * this is just a sanity test that we can retrieve the quota,
>> +     * and inode limits have the same units across both calls.
>> +     */
>> +    printf("id        %u\n", dqb.dqb_id);
>> +    printf("ihard     %llu\n", (unsigned long long)dqb.dqb_ihardlimit);
>> +    printf("isoft     %llu\n", (unsigned long long)dqb.dqb_isoftlimit);
>> +
>> +    if (verbose)
>> +        printf("====Q_XGETNEXTQUOTA====\n");
>> +    cmd = QCMD(Q_XGETNEXTQUOTA, USRQUOTA);
>> +    if (quotactl(cmd, device, id, (void *)&xqb) < 0) {
>> +        perror("Q_XGETNEXTQUOTA");
>> +        return 1;
>> +    }
>> +
>> +    printf("id        %u\n", xqb.d_id);
>> +    printf("ihard     %llu\n", xqb.d_ino_hardlimit);
>> +    printf("isoft     %llu\n", xqb.d_ino_softlimit);
>> +
>> +    return 0;
>> +}
>> diff --git a/tests/generic/244 b/tests/generic/244
>> new file mode 100755
>> index 0000000..eb5a5ab
>> --- /dev/null
>> +++ b/tests/generic/244
>> @@ -0,0 +1,131 @@
>> +#! /bin/bash
>> +# FS QA Test 244
>> +#
>> +# test out "sparse" quota ids retrieved by Q_GETNEXTQUOTA
>> +#
>> +# Designed to use the new Q_GETNEXTQUOTA quotactl
>> +#
>> +#-----------------------------------------------------------------------
>> +# Copyright (c) 2016 Red Hat, Inc.  All Rights Reserved.
>> +#
>> +# This program is free software; you can redistribute it and/or
>> +# modify it under the terms of the GNU General Public License as
>> +# published by the Free Software Foundation.
>> +#
>> +# This program is distributed in the hope that it would be useful,
>> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> +# GNU General Public License for more details.
>> +#
>> +# You should have received a copy of the GNU General Public License
>> +# along with this program; if not, write the Free Software Foundation,
>> +# Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
>> +#-----------------------------------------------------------------------
>> +#
>> +
>> +seq=`basename $0`
>> +seqres=$RESULT_DIR/$seq
>> +echo "QA output created by $seq"
>> +
>> +here=`pwd`
>> +tmp=/tmp/$$
>> +status=1    # failure is the default!
>> +trap "_cleanup; exit \$status" 0 1 2 3 15
>> +
>> +_cleanup()
>> +{
>> +    cat $tmp.IDs >> $seqres.full
>> +    cd /
>> +    rm -f $tmp.*
>> +}
>> +
>> +# get standard environment, filters and checks
>> +. ./common/rc
>> +. ./common/filter
>> +. ./common/quota
>> +
>> +# remove previous $seqres.full before test
>> +rm -f $seqres.full
>> +
>> +# real QA test starts here
>> +
>> +_supported_fs generic
>> +_supported_os Linux
>> +_require_quota
>> +_require_scratch
>> +
>> +scratch_unmount 2>/dev/null
>> +_scratch_mkfs >> $seqres.full 2>&1
>> +_scratch_mount "-o usrquota,grpquota"
>> +quotacheck -u -g $SCRATCH_MNT 2>/dev/null
>> +quotaon $SCRATCH_MNT 2>/dev/null
>> +_scratch_unmount
>> +
>> +TYPES="u g"
>> +MOUNT_OPTIONS="-o usrquota,grpquota"
>> +
>> +_qmount
>> +quotaon $SCRATCH_MNT 2>/dev/null
>> +
>> +# Ok, do we even have GETNEXTQUOTA?  Querying ID 0 should work.
>> +$here/src/test-nextquota -i 0 -u -d $SCRATCH_DEV &> $seqres.full || \
>> +    _notrun "No GETNEXTQUOTA support"
>> +
>> +echo "Launch all quotas"
>> +
>> +# Ideally we'd carefully test edge conditions of "sparse"
>> +# quota ids at beginnings and ends of otherwise empty disk
>> +# blocks, etc, but that's pretty fs-specific.
>> +# So just spray a bunch of random IDs into quota, and make
>> +# sure we get them all back.
>> +
>> +ITERATIONS=100
>> +
>> +# A few extra on the off chance we get dups
>> +for I in `seq 1 $(($ITERATIONS+10))`; do
>> +    ID=`od -N 4 -t uL -An /dev/urandom | tr -d " "`
>> +    echo $ID >> $tmp.1
>> +done
>> +
>> +# sort & uniq to remove dups & facilitate reading them back
>> +# On the off chance we got ID 0, remove it.
>> +sort -n $tmp.1 | uniq | head -n ${ITERATIONS} | grep -vw 0 > $tmp.IDs
>> +
>> +# Populate a bunch of random quotas on the filesystem:
>> +for TYPE in u g; do
>> +    for ID in `cat $tmp.IDs`; do
>> +        setquota -${TYPE} $ID $ID $ID $ID $ID $SCRATCH_MNT
>> +        touch ${SCRATCH_MNT}/${ID}
>> +        chown ${ID} ${SCRATCH_MNT}/${ID}
>> +    done
>> +done
>> +
>> +# remount just for kicks, make sure we get it off disk
>> +_scratch_unmount
>> +_qmount
>> +quotaon $SCRATCH_MNT 2>/dev/null
>> +
>> +# Read them back by iterating based on quotas returned.
>> +# This should match what we set, even if we don't directly
>> +# ask for each exact id, but just ask for "next" id after
>> +# each one we got back last.
>> +for TYPE in u g; do
>> +    # root is always there but not in our random IDs; start at 1
>> +    NEXT=1
>> +    for ID in `cat $tmp.IDs`; do
>> +        echo "Trying ID $NEXT expecting $ID" >> $seqres.full
>> +        Q=`$here/src/test-nextquota -i $NEXT -${TYPE} -d $SCRATCH_DEV` \
>> +             || _fail "test-nextquota failed: $Q"
>> +        echo $Q >> $seqres.full
>> +        # ID and its inode limits should match
>> +        echo "$Q" | grep -qw ${ID} || _fail "Didn't get id $ID"
>> +        # Get the ID returned from the test
>> +        NEXT=`echo "$Q" | grep ^id | awk '{print $NF}' | head -n 1`
>> +        # Advance that ID by one, and ask for another search
>> +        let NEXT=NEXT+1
>> +    done
>> +done
>> +
>> +# success, all done
>> +status=0
>> +exit
>> diff --git a/tests/generic/244.out b/tests/generic/244.out
>> new file mode 100644
>> index 0000000..df76947
>> --- /dev/null
>> +++ b/tests/generic/244.out
>> @@ -0,0 +1,2 @@
>> +QA output created by 244
>> +Launch all quotas
>> diff --git a/tests/generic/group b/tests/generic/group
>> index 8ed383f..860ff4a 100644
>> --- a/tests/generic/group
>> +++ b/tests/generic/group
>> @@ -246,6 +246,7 @@
>> 241 auto
>> 242 auto quick clone
>> 243 auto quick clone
>> +244 auto quick quota
>> 245 auto quick dir
>> 246 auto quick rw
>> 247 auto quick rw
>> 
>> 
>> --
>> To unsubscribe from this list: send the line "unsubscribe fstests" in
>> the body of a message to majordomo@xxxxxxxxxxxxxxx
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> --
> To unsubscribe from this list: send the line "unsubscribe fstests" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
--
To unsubscribe from this list: send the line "unsubscribe fstests" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Filesystems Development]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux