From patchwork Fri Jan 22 00:02:29 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Sandeen X-Patchwork-Id: 8085831 Return-Path: X-Original-To: patchwork-fstests@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id CF6059F818 for ; Fri, 22 Jan 2016 00:02:38 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 934E220460 for ; Fri, 22 Jan 2016 00:02:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id BBA0F20457 for ; Fri, 22 Jan 2016 00:02:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751111AbcAVACe (ORCPT ); Thu, 21 Jan 2016 19:02:34 -0500 Received: from sandeen.net ([63.231.237.45]:38544 "EHLO sandeen.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750991AbcAVACd (ORCPT ); Thu, 21 Jan 2016 19:02:33 -0500 Received: from Liberator.local (70-90-76-85-BusName-mn.hfc.comcastbusiness.net [70.90.76.85]) (using TLSv1.2 with cipher DHE-RSA-AES128-SHA (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id 4236163CBCEB for ; Thu, 21 Jan 2016 18:02:30 -0600 (CST) To: fstests From: Eric Sandeen Subject: [PATCH] test Q_GETNEXTQUOTA X-Enigmail-Draft-Status: N1110 Message-ID: <56A17195.8090400@sandeen.net> Date: Thu, 21 Jan 2016 18:02:29 -0600 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:38.0) Gecko/20100101 Thunderbird/38.5.1 MIME-Version: 1.0 Sender: fstests-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: fstests@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- -- To unsubscribe from this list: send the line "unsubscribe fstests" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html 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 +#include +#include +#include +#include +#include + +/* + * 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