Whamcloud - gitweb
New tag 2.14.52
[fs/lustre-release.git] / lustre / tests / metadata-updates.sh
1 #!/bin/bash
2
3 # A Metadata Update Test tests that
4 # metadata updates are properly completed when
5 # multiple clients create/delete files and modify the attributes of files.
6
7 set -e
8
9 ONLY=${ONLY:-"$*"}
10
11 LUSTRE=${LUSTRE:-$(dirname $0)/..}
12 . $LUSTRE/tests/test-framework.sh
13 init_test_env $@
14 init_logging
15
16 #Bug number for skipped test:
17 ALWAYS_EXCEPT="$METADATA_UPDATES_EXCEPT "
18 # UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT LIST
19 build_test_filter
20
21 TRACE=${TRACE:-"+x"}
22
23 TESTDIR=${TESTDIR:-$DIR/d0.$(basename $0 .sh)}
24
25 NODES_TO_USE=${NODES_TO_USE:-$CLIENTS}
26
27 [ -z $CLIENTS ] && NODES_TO_USE=$(hostname)
28
29 # hostname could differ from a network interface
30 # configured for NODES_TO_USE, bug 23961
31 # the test dir on each host is created based on `hostname` of this host
32 HOSTS=$(comma_list $(do_nodes $NODES_TO_USE "echo \\\$(hostname)"))
33
34 FILE=testfile
35 FILE_SIZE=1024
36 CURRENT_MODE=0644
37 NEW_MODE=0222
38 NEW_ATIME="2001-01-01 GMT"
39 NEW_MTIME="2005-05-05 GMT"
40
41 test_USER=$(id -u -n)
42 test_GROUP=$(id -g -n)
43
44 SUMFILE=$TESTDIR/mdsum
45
46 NUM_FILES=1000
47
48 log "===== $0 ====== "
49
50 check_and_setup_lustre
51
52 cleanup_prepare () {
53
54         do_nodes $NODES_TO_USE "set $TRACE;
55         DIR=$TESTDIR/\\\$(hostname);
56         TESTFILE=\\\$DIR/$FILE;
57         rm -f \\\$TESTFILE;
58         rm -f $SUMFILE;
59         rmdir \\\$DIR 2>/dev/null;
60         mkdir -p \\\$DIR" || return ${PIPESTATUS[0]}
61         return 0;
62 }
63
64 do_mknod () {
65         log "Creating file(s) by mknod (2) ... "
66
67         do_nodes $NODES_TO_USE "set $TRACE;
68         TESTFILE=$TESTDIR/\\\$(hostname)/$FILE;
69         mcreate \\\$TESTFILE; " || return ${PIPESTATUS[0]}
70         return 0
71 }
72
73 do_write () {
74         do_nodes $NODES_TO_USE "set $TRACE;
75         TESTFILE=$TESTDIR/\\\$(hostname)/$FILE;
76         dd if=/dev/zero of=\\\$TESTFILE bs=$FILE_SIZE count=1 2>/dev/null ||
77                 exit 54;
78         echo \\\$(hostname) | dd of=\\\$TESTFILE conv=notrunc 2>/dev/null ||
79                 exit 55;
80         md5sum \\\$TESTFILE >> $SUMFILE; " || return ${PIPESTATUS[0]}
81         return 0
82 }
83
84 do_check_data () {
85         log "Checking file(s) data ... md5sum : "
86         cat $SUMFILE
87
88         do_nodesv $NODES_TO_USE "md5sum --check $SUMFILE" ||
89                 return ${PIPESTATUS[0]}
90         return 0
91 }
92
93 do_truncate () {
94         log "Truncating file(s) ... "
95
96         do_nodes $NODES_TO_USE "set $TRACE;
97         TESTFILE=$TESTDIR/\\\$(hostname)/$FILE;
98         $TRUNCATE \\\$TESTFILE 0" || return ${PIPESTATUS[0]}
99
100         FILE_SIZE=0
101         return 0
102 }
103
104 # check st_uid, st_gid, st_size, st_mode
105 get_stat () {
106         local attr="$test_USER $test_GROUP $FILE_SIZE $CURRENT_MODE"
107
108         log "Checking file(s) attributes ... "
109
110         do_nodesv $NODES_TO_USE "set $TRACE;
111 for HOST in ${HOSTS//,/ } ; do
112     TESTFILE=$TESTDIR/\\\$HOST/$FILE;
113     tmp=\\\$(stat -c \\\"%U %G %s 0%a\\\" \\\$TESTFILE);
114     echo \\\"\\\$TESTFILE [ uid gid size mode ] expected : $attr ;  got : \\\$tmp \\\";
115     if [ x\\\"\\\$tmp\\\" != x\\\"$attr\\\" ] ; then
116         echo \\\"Wrong file attributes\\\";
117         exit 56;
118     fi;
119 done " || return ${PIPESTATUS[0]}
120         return 0
121 }
122
123 do_chmod () {
124         log "Performing chmod 0$NEW_MODE ..."
125
126         do_nodes $NODES_TO_USE "set $TRACE;
127         TESTFILE=$TESTDIR/\\\$(hostname)/$FILE;
128         chmod $NEW_MODE \\\$TESTFILE" || return ${PIPESTATUS[0]}
129
130         CURRENT_MODE=$NEW_MODE
131         return 0
132 }
133
134 do_change_timestamps () {
135         log "Changing atime, mtime ..."
136
137         do_nodes $NODES_TO_USE " set $TRACE;
138         TESTFILE=$TESTDIR/\\\$(hostname)/$FILE;
139         touch -c --date=\\\"$NEW_ATIME\\\" -a \\\$TESTFILE;
140         touch -c --date=\\\"$NEW_MTIME\\\" -m \\\$TESTFILE " ||
141                 return ${PIPESTATUS[0]}
142         return 0
143 }
144
145 # check st_atime, st_mtime
146 do_check_timestamps () {
147         local atime=$(date --date="$NEW_ATIME" +%s)
148         local mtime=$(date --date="$NEW_MTIME" +%s)
149
150         local times="$atime $mtime"
151
152         log "Checking atime, mtime ... "
153
154         do_nodesv $NODES_TO_USE "set $TRACE;
155 for HOST in ${HOSTS//,/ } ; do
156     TESTFILE=$TESTDIR/\\\$HOST/$FILE;
157     tmp=\\\$(stat -c \\\"%X %Y\\\" \\\$TESTFILE);
158     if [ x\\\"\\\$tmp\\\" != x\\\"$times\\\" ] ; then
159        echo \\\"\\\$TESTFILE [ atime mtime ] expected : $times ;  got : \\\$tmp \\\";
160        RC=57;
161     fi;
162 done;
163 exit \\\$RC" || return ${PIPESTATUS[0]}
164         return 0
165 }
166
167 do_fill_dir () {
168         log "Filling up directories ... files : f1 ... f$NUM_FILES) ... "
169
170         do_nodes $NODES_TO_USE "set $TRACE;
171         TESTFILE=$TESTDIR/\\\$(hostname)/$FILE;
172         rm -f \\\$TESTFILE;
173         DIR=$TESTDIR/\\\$(hostname);
174         for i in \\\$(seq $NUM_FILES) ; do
175                 touch \\\$DIR/f\\\$i;
176         done " || return ${PIPESTATUS[0]}
177         return 0
178 }
179
180 check_dir_contents () {
181         local num_files=${1:-1}
182
183         log "Directory contents should exist: f$num_files ... f$NUM_FILES)"
184         do_nodes $NODES_TO_USE "set $TRACE;
185 for HOST in ${HOSTS//,/ } ; do
186     DIR=$TESTDIR/\\\$HOST;
187     for i in \\\$(seq $NUM_FILES -1 $num_files) ; do
188         if ! [ -f \\\$DIR/f\\\$i ] ; then
189             echo \\\"ERROR: file \\\$DIR/f\\\$i should exist\\\";
190             RC=1;
191         fi;
192     done;
193     for i in \\\$(seq $(($num_files - 1 ))) ; do
194         if [ -f \\\$DIR/f\\\$i ] ; then
195             echo \\\"ERROR: deleted file \\\$DIR/f\\\$i exists\\\";
196             RC=1;
197         fi;
198     done;
199 done;
200 exit \\\$RC " || return ${PIPESTATUS[0]}
201         return 0
202 }
203
204 do_partial_delete () {
205         local num_files=$1
206
207         log "Deleting files ... f1 ... f$num_files ... "
208         do_nodes $NODES_TO_USE "set $TRACE;
209 DIR=$TESTDIR/\\\$(hostname);
210 for i in \\\$(seq $num_files) ; do
211     if ! rm -f \\\$DIR/f\\\$i ; then
212         exit 1;
213     fi;
214 done " || return ${PIPESTATUS[0]}
215         return 0
216 }
217
218 chmod 0777 $MOUNT   || exit 1
219 mkdir -p $TESTDIR   || exit 1
220 chmod 0777 $TESTDIR || exit 1
221
222 cleanup_prepare     || error_exit "cleanup failed"
223
224 test_1(){
225         log "Create files (mknod (2)) and write data"
226         do_mknod || error "mknod failed"
227         do_write || error "write data failed"
228         log "Check data and file attributes."
229         do_check_data || error "md5sum verification failed"
230         get_stat || error "attributes check failed"
231
232         # file attributes modification
233         log "File attributes modification."
234         do_chmod || error "chmod failed"
235         get_stat || error "wrong attributes after chmod"
236
237         do_change_timestamps || error "timestamps change failed"
238         do_check_timestamps || error "wrong timestamps"
239
240         # truncate file(s) to 0 size, check new file size
241         log "Truncate file(s) to 0 size, check new file size."
242         do_truncate || error "truncate failed"
243         get_stat || error "wrong attributes after truncate"
244 }
245 run_test 1 "create files (mknod), write and check data, truncate files"
246
247 test_2() {
248         do_fill_dir || error "dir creation failed"
249         check_dir_contents || error "dir contents check failed"
250
251         do_partial_delete $(($NUM_FILES / 2)) || error "delete failed"
252         check_dir_contents $(($NUM_FILES / 2 + 1)) ||
253                 error "dir contents check after delete failed"
254 }
255 run_test 2 "directory content create, check, delete files , check"
256
257 test_3() {
258         WRITE_DISJOINT=${WRITE_DISJOINT:-$(which write_disjoint 2> /dev/null)} || true
259         disjoint_file=$TESTDIR/$tfile
260         numloops=1000
261
262         [ ! -f "$WRITE_DISJOINT" ] && skip_env "write_disjoint not found"
263
264         set $TRACE
265         generate_machine_file $NODES_TO_USE $MACHINEFILE
266         mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
267                 -np $(get_node_count ${NODES_TO_USE//,/ }) \
268                 $WRITE_DISJOINT -f $disjoint_file -n $numloops ||
269                         error "mpi_run failed"
270
271         rm -f $MACHINEFILE
272 }
273 run_test 3 "write_disjoint test"
274
275 complete $SECONDS
276 rm -rf $TESTDIR
277 check_and_cleanup_lustre
278 exit_status