summaryrefslogtreecommitdiff
path: root/tests/ext4/022
blob: 321050b35cde256908ba1106c466add3e6fe747e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2016 SUSE Linux Products GmbH.  All Rights Reserved.
#
# FS QA Test 022
#
# Test extending of i_extra_isize code
#
. ./common/preamble
_begin_fstest auto quick attr dangerous

do_setfattr()
{
	$SETFATTR_PROG $@ 2>&1 | _filter_scratch
}

# Import common functions.
. ./common/filter
. ./common/attr

# real QA test starts here
_supported_fs ext4
_require_scratch
_require_dumpe2fs
_require_command "$DEBUGFS_PROG" debugfs
_require_attrs

# Block size
BLOCK_SIZE=4096
if [[ $(get_page_size) -ne $BLOCK_SIZE ]]; then
       _exclude_scratch_mount_option dax
fi
# Use large inodes to have enough space for experimentation
INODE_SIZE=1024
# We leave this amount of bytes for xattrs
XATTR_SPACE=256
# We grow extra_isize by this much
GROW_EXTRA_ISIZE=80
# We grow minimum requested isize by this much
GROW_MIN_EXTRA_ISIZE=16

export MKFS_OPTIONS="-I $INODE_SIZE -b $BLOCK_SIZE"
_scratch_mkfs >> $seqres.full 2>&1

ISIZE=$($DUMPE2FS_PROG -h $SCRATCH_DEV 2>/dev/null |
	grep "^Desired extra isize:" | awk '{print $4}')
# 32 bytes for header and 4 bytes for terminator
BLOCK_XATTR_SPACE=$(($BLOCK_SIZE - 36))
GOOD_OLD_ISIZE=128
WANT_ISIZE=$(($INODE_SIZE-$GOOD_OLD_ISIZE-$XATTR_SPACE))
NEW_ISIZE=$(($WANT_ISIZE+$GROW_EXTRA_ISIZE))
NEW_MIN_ISIZE=$(($WANT_ISIZE+$GROW_MIN_EXTRA_ISIZE))

if [ $WANT_ISIZE -lt $ISIZE ]; then
	_notrun "This test requires at least $XATTR_SPACE free in the inode"
fi

$DEBUGFS_PROG -w -R "ssv want_extra_isize $WANT_ISIZE" $SCRATCH_DEV >> $seqres.full 2>&1
$DEBUGFS_PROG -w -R "ssv min_extra_isize $WANT_ISIZE" $SCRATCH_DEV >> $seqres.full 2>&1

_scratch_mount

FNAMES=("empty" "couple_xattrs" "just_enough_xattrs" "one_extra_xattr"
	"full_xattrs" "one_extra_xattr_ext" "full_xattrs_ext"
	"full_xattrs_almost_full_ext" "full_xattrs_full_ext")
create_xattr_file()
{
	FILE=$SCRATCH_MNT/${FNAMES[$1]}
	touch $FILE
	for (( i = 0; i < $2; i++ )); do
		do_setfattr -n "user.$i" -v "aa" $FILE || break
	done
}

# Test file without xattrs
create_xattr_file 0 0

# Test file with couple of xattrs but which still has enough space
# One xattr consumes 24 bytes + 4 bytes for header + 4 bytes for terminator
# => 104 bytes consumed (152 bytes still free)
create_xattr_file 1 4

# Test file with xattrs which still has just enough space
# One xattr consumes 24 bytes + 4 bytes for header + 4 bytes for terminator
# => 176 bytes consumed (80 bytes still free)
create_xattr_file 2 7

# Test file with xattrs which has one xattr which needs moving
# One xattr consumes 24 bytes + 4 bytes for header + 4 bytes for terminator
# => 200 bytes consumed (56 bytes still free)
create_xattr_file 3 8

# Test file with xattrs which has xattr space almost full
# One xattr consumes 24 bytes + 4 bytes for header + 4 bytes for terminator
# => 248 bytes consumed (8 bytes still free)
create_xattr_file 4 10

# Test file with xattrs which has one xattr which needs moving and external
# xattr block allocated
# One xattr consumes 24 bytes + 4 bytes for header + 4 bytes for terminator
# => 200 bytes consumed (56 bytes still free)
create_xattr_file 5 8
do_setfattr -n "user.e0" -v "01234567890123456789012345678901234567890123456789" "$SCRATCH_MNT/${FNAMES[5]}"

# Test file with xattrs which has xattr space in inode almost full and external
# xattr block allocated
# One xattr consumes 24 bytes + 4 bytes for header + 4 bytes for terminator
# => 248 bytes consumed (8 bytes still free)
create_xattr_file 6 11

# Test file with xattrs which has xattr space in inode almost full and external
# xattr block allocated and almost full so that inode can still expand to
# s_min_extra_isize
# 10 xattrs fit into inode, rest goes into xattr block (one xattr consumes
# 24 bytes)
create_xattr_file 7 $((10 + ($BLOCK_XATTR_SPACE - $GROW_MIN_EXTRA_ISIZE) / 24))

# Test file with xattrs which has xattr space in inode almost full and external
# xattr block allocated and full
# 10 xattrs fit into inode, rest goes into xattr block (one xattr consumes
# 24 bytes)
create_xattr_file 8 $((10 + $BLOCK_XATTR_SPACE / 24))

_scratch_unmount

# Filesystem prepared, update extra_isize

$DEBUGFS_PROG -w -R "ssv want_extra_isize $NEW_ISIZE" $SCRATCH_DEV >> $seqres.full 2>&1
$DEBUGFS_PROG -w -R "ssv min_extra_isize $NEW_MIN_ISIZE" $SCRATCH_DEV >> $seqres.full 2>&1

_scratch_mount

# Dirty each inode to force expansion of extra_isize
for FILE in ${FNAMES[@]}; do
	echo "aaaa" >$SCRATCH_MNT/$FILE
done

# Dump all xattrs to see whether nothing broke
for FILE in ${FNAMES[@]}; do
	_getfattr -h -d --absolute-names $SCRATCH_MNT/$FILE 2>/dev/null | \
		_filter_scratch | sort
done

_scratch_unmount

# Dump everything via debugfs to check whether sizes got extended as expected
for FILE in ${FNAMES[@]}; do
	$DEBUGFS_PROG -R "stat $FILE" $SCRATCH_DEV 2>/dev/null | \
		grep "^Size of extra inode fields:"
done

# success, all done
status=0
exit