xfs: quotas and idmapped mounts
[xfstests-dev.git] / tests / xfs / 152
1 #! /bin/bash
2 # SPDX-License-Identifier: GPL-2.0+
3 #
4 # Copyright (c) 2021 Christian Brauner <christian.brauner@ubuntu.com>
5 # All Rights Reserved.
6 #
7 # FS QA Test No. 152
8 #
9 # Exercise basic xfs_quota functionality (user/group/project quota)
10 # Use of "sync" mount option here is an attempt to get deterministic
11 # allocator behaviour.
12 #
13 seq=`basename $0`
14 seqres=$RESULT_DIR/$seq
15 echo "QA output created by $seq"
16
17 here=`pwd`
18 tmp=/tmp/$$
19 status=1        # failure is the default!
20 trap "_cleanup; exit \$status" 0 1 2 3 15
21
22 wipe_mounts()
23 {
24         umount "${SCRATCH_MNT}/idmapped" >/dev/null 2>&1
25         _scratch_unmount >/dev/null 2>&1
26 }
27
28 _cleanup()
29 {
30         cd /
31         wipe_mounts
32         rm -f $tmp.*
33 }
34
35 # get standard environment, filters and checks
36 . ./common/rc
37 . ./common/filter
38 . ./common/quota
39
40 # remove previous $seqres.full before test
41 rm -f $seqres.full
42
43 # real QA test starts here
44 _supported_fs xfs
45 _require_idmapped_mounts
46 _require_test_program "idmapped-mounts/mount-idmapped"
47 _require_scratch
48 _require_xfs_quota
49 _require_user fsgqa
50 _require_user fsgqa2
51 _require_group fsgqa
52 _require_group fsgqa2
53
54 _scratch_mkfs_xfs >>$seqres.full 2>&1
55
56 uqid=`id -u fsgqa`
57 gqid=`id -g fsgqa`
58
59 uqid2=`id -u fsgqa2`
60 gqid2=`id -g fsgqa2`
61
62 pqid=10
63 cat >$tmp.projects <<EOF
64 $pqid:$SCRATCH_MNT
65 EOF
66
67 cat >$tmp.projid <<EOF
68 root:0
69 fsgqa:$pqid
70 EOF
71
72 create_files_unmapped()
73 {
74         local bs=$1
75         local inum=$2
76
77         echo "Using type=$type id=$id" >> $seqres.full
78
79         for ((i=0; i<$((inum-1)); i++)); do
80                 _file_as_id $SCRATCH_MNT/unmapped/inode$i $id $type 1024 0
81         done
82
83         _file_as_id $SCRATCH_MNT/unmapped/block $id $type $bs 1
84 }
85
86 create_files_idmapped()
87 {
88         local bs=$1
89         local inum=$2
90
91         echo "Using type=$type id=$id2" >> $seqres.full
92
93         for ((i=0; i<$((inum-1)); i++)); do
94                 _file_as_id $SCRATCH_MNT/idmapped/inode$i $id2 $type 1024 0
95         done
96
97         _file_as_id $SCRATCH_MNT/idmapped/block $id2 $type $bs 1
98 }
99
100 clean_files()
101 {
102         rm -rf $SCRATCH_MNT/unmapped 2>/dev/null
103         rm -rf $SCRATCH_MNT/idmapped 2>/dev/null
104         rm -rf $tmp.quot 2>/dev/null
105         rm -rf $tmp.quota 2>/dev/null
106 }
107
108 filter_quot()
109 {
110         _filter_quota | grep -v "root \|\#0 " \
111                 | sed -e '/#[0-9]*/s/#[0-9]*/#ID/g'
112 }
113
114 filter_report()
115 {
116         _filter_quota | grep -v "^root \|^\#0 " \
117                 | sed -e '/^#[0-9]*/s/^#[0-9]*/#ID/g'
118 }
119
120 filter_quota()
121 {
122         _filter_quota | sed -e "/Disk quotas for/s/([0-9]*)/(ID)/g" \
123                             -e "/Disk quotas for/s/#[0-9]*/#ID/g"
124 }
125
126 filter_state()
127 {
128         _filter_quota | sed -e "s/Inode: #[0-9]* (0 blocks, 0 extents)/Inode: #[INO] (0 blocks, 0 extents)/g" \
129                             -e "s/Inode: #[0-9]* ([0-9]* blocks, [0-9]* extents)/Inode: #[INO] (X blocks, Y extents)/g" \
130                             -e "/[0-9][0-9]:[0-9][0-9]:[0-9][0-9]/s/ [0-9][0-9]:[0-9][0-9]:[0-9][0-9]//g" \
131                             -e '/max warnings:/d'
132 }
133
134 test_quot()
135 {
136         local opt="$*"
137
138         echo "checking quot command (type=$type)"
139         $XFS_QUOTA_PROG -D $tmp.projects -P $tmp.projid -x \
140                         -c "quot -$type $opt -bi" $SCRATCH_MNT | filter_quot
141 }
142
143 test_report()
144 {
145         local opt="$*"
146
147         echo "checking report command (type=$type)"
148         $XFS_QUOTA_PROG -D $tmp.projects -P $tmp.projid -x \
149                         -c "report -$type $opt -bi" \
150                         $SCRATCH_MNT | filter_report
151 }
152
153 test_quota()
154 {
155         local opt="$*"
156
157         echo "checking quota command (type=$type)"
158         $XFS_QUOTA_PROG -D $tmp.projects -P $tmp.projid -x \
159                         -c "quota -$type $opt -bi $id" \
160                         $SCRATCH_MNT | filter_quota
161 }
162
163 test_limit()
164 {
165         local bs=$1
166         local bh=$2
167         local is=$3
168         local ih=$4
169
170         echo "checking limit command (type=$type, bsoft=$bs, bhard=$bh, isoft=$is, ihard=$ih)"
171         $XFS_QUOTA_PROG -D $tmp.projects -P $tmp.projid -x \
172                         -c "limit -$type bsoft=$bs bhard=$bh fsgqa" \
173                         -c "limit -$type isoft=$is ihard=$ih fsgqa" \
174                         $SCRATCH_MNT
175
176         # let the timer day transition happen
177         sleep 2
178 }
179
180 test_timer()
181 {
182         echo "checking timer command (type=$type)"
183         # set 3days+1h for time won't become 2days soon
184         $XFS_QUOTA_PROG -D $tmp.projects -P $tmp.projid -x \
185                         -c "timer -$type -bi 73h" \
186                         $SCRATCH_MNT | _filter_scratch
187 }
188
189 test_disable()
190 {
191         echo "checking disable command (type=$type)"
192         $XFS_QUOTA_PROG -D $tmp.projects -P $tmp.projid -x \
193                         -c "disable -$type -v" \
194                         $SCRATCH_MNT | filter_state
195 }
196
197 test_enable()
198 {
199         echo "checking enable command (type=$type)"
200         $XFS_QUOTA_PROG -D $tmp.projects -P $tmp.projid -x \
201                         -c "enable -$type -v" $SCRATCH_MNT | filter_state
202 }
203
204 test_off()
205 {
206         echo "checking off command (type=$type)"
207         $XFS_QUOTA_PROG -D $tmp.projects -P $tmp.projid -x \
208                         -c "off -$type -v" $SCRATCH_MNT | _filter_scratch
209 }
210
211 test_remove()
212 {
213         echo "checking remove command (type=$type)"
214         $XFS_QUOTA_PROG -D $tmp.projects -P $tmp.projid -x \
215                         -c "remove -$type -v" \
216                         $SCRATCH_MNT | _filter_scratch
217 }
218
219 test_state()
220 {
221         echo "checking state command (type=$type)"
222         $XFS_QUOTA_PROG -D $tmp.projects -P $tmp.projid -x \
223                         -c "state -$type" $SCRATCH_MNT | filter_state
224 }
225
226 test_dump()
227 {
228         echo "checking dump command (type=$type)"
229         rm -f $tmp.backup 2>>/dev/null
230         $XFS_QUOTA_PROG -D $tmp.projects -P $tmp.projid -x \
231                         -c "dump -$type -f $tmp.backup" \
232                         $SCRATCH_MNT | _filter_scratch
233 }
234
235 test_restore()
236 {
237         echo "checking restore command (type=$type)"
238         $XFS_QUOTA_PROG -D $tmp.projects -P $tmp.projid -x \
239                         -c "restore -$type -f $tmp.backup" \
240                         $SCRATCH_MNT | _filter_scratch
241 }
242
243 wipe_scratch()
244 {
245         wipe_mounts
246         _scratch_mkfs_xfs >>$seqres.full 2>&1
247 }
248
249 qmount_idmapped()
250 {
251         wipe_mounts
252         _try_scratch_mount || _fail "qmount failed"
253
254         mkdir -p "${SCRATCH_MNT}/unmapped"
255         mkdir -p "${SCRATCH_MNT}/idmapped"
256
257         $here/src/idmapped-mounts/mount-idmapped \
258                 --map-mount b:$id:$id2:1 \
259                 --map-mount b:0:0:1 \
260                 "$SCRATCH_MNT/unmapped" "$SCRATCH_MNT/idmapped" || _fail "mount-idmapped failed"
261
262         chmod ugo+rwx $SCRATCH_MNT
263         chmod ugo+rwx $SCRATCH_MNT/unmapped
264         chmod ugo+rwx $SCRATCH_MNT/idmapped
265 }
266
267 test_xfs_quota()
268 {
269         # init quota
270         echo "init quota limit and timer, and dump it"
271         if [ "$idmapped" -eq 1 ]; then
272                 echo "create_files_idmapped 1024k 15"; create_files_idmapped 1024k 15
273         else
274                 echo "create_files_unmapped 1024k 15"; create_files_unmapped 1024k 15
275         fi
276         echo "quota remount"; qmount_idmapped
277         echo ; test_quot
278         echo ; test_timer
279         echo ; test_limit 512k 2048k 10 20
280         echo ; test_dump
281
282         # report options test
283         echo "report options test"
284         echo ; test_report
285         echo "-N option"; test_report -N
286         echo "-L -U options"; test_report -L $id -U $id
287         echo "-t option"; test_report -t
288         echo "-n option"; test_report -n
289         echo "-h option"; test_report -h
290
291         # quot options test
292         echo "quot options test"
293         echo ; test_quot
294         echo "-f option"; test_quot -f $tmp.quot
295         cat $tmp.quot | filter_quot
296         echo "-n option"; test_quot -n
297
298         # quota options test
299         echo ; test_quota
300         echo "-f option"; test_quota -f $tmp.quota
301         cat $tmp.quota | filter_quota
302         echo "-N option"; test_quota -N
303         echo "-n option"; test_quota -n
304         echo "-h option"; test_quota -h
305
306         # disable/enable test
307         echo "disable quota"
308         echo ; test_disable
309         echo ; test_report -N
310         echo "expect a remove error at here"; test_remove
311         echo ; test_enable
312         echo ; test_report -N
313
314         # off and remove test
315         echo "off and remove test"
316         echo ; test_limit 100m 100m 100 100
317         echo ; test_quota -N
318         echo ; test_off
319         echo ; test_state
320         echo ; test_remove
321         echo ; test_report -N
322         echo "quota remount"; qmount_idmapped
323         echo ; test_report -N
324
325         # restore test
326         echo "restore quota"
327         echo ; test_restore
328         echo ; test_report -N
329         echo ; test_state
330         echo "cleanup files"; clean_files
331 }
332
333 echo "----------------------- uquota,sync,unmapped ---------------------------"
334 wipe_scratch
335 _qmount_option "uquota,sync"
336 type=u
337 id=$uqid
338 id2=$uqid2
339 idmapped=0
340 qmount_idmapped
341 test_xfs_quota
342
343 echo "----------------------- uquota,sync,idmapped ---------------------------"
344 wipe_scratch
345 _qmount_option "uquota,sync"
346 type=u
347 id=$uqid
348 id2=$uqid2
349 idmapped=1
350 qmount_idmapped
351 test_xfs_quota
352
353 echo "----------------------- gquota,sync,unmapped ---------------------------"
354 wipe_scratch
355 _qmount_option "gquota,sync"
356 type=g
357 id=$gqid
358 id2=$gqid2
359 idmapped=0
360 qmount_idmapped
361 test_xfs_quota
362
363 echo "----------------------- gquota,sync,idmapped ---------------------------"
364 wipe_scratch
365 _qmount_option "gquota,sync"
366 type=g
367 id=$gqid
368 id2=$gqid2
369 idmapped=1
370 qmount_idmapped
371 test_xfs_quota
372
373 wipe_mounts
374
375 # success, all done
376 status=0
377 exit