Whamcloud - gitweb
b=23515 recovery_*_scale tests need more than 2 clients
[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 LUSTRE=${LUSTRE:-$(cd $(dirname $0)/..; echo $PWD)}
10 . $LUSTRE/tests/test-framework.sh
11 init_test_env $@
12 . ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh}
13 init_logging
14
15 TRACE=${TRACE:-"+x"}
16
17 TESTDIR=${TESTDIR:-$DIR/d0.$(basename $0 .sh)}
18
19 NODES_TO_USE=${NODES_TO_USE:-$CLIENTS}
20
21 [ -z $CLIENTS ] && NODES_TO_USE=$(hostname)
22
23 FILE=testfile
24 FILE_SIZE=1024
25 CURRENT_MODE=0644
26 NEW_MODE=0222
27 NEW_ATIME="2001-01-01 GMT"
28 NEW_MTIME="2005-05-05 GMT"
29
30 test_UID=$(id -u)
31 test_GID=$(id -g)
32
33 SUMFILE=$TESTDIR/mdsum
34
35 NUM_FILES=1000
36
37 WRITE_DISJOINT=${WRITE_DISJOINT:-$(which write_disjoint 2> /dev/null)} || true
38 WRITE_DISJOINT_FILE=$TESTDIR/f0.write_disjoint_file
39 NUMLOOPS=1000
40
41 log "===== $0 ====== "
42
43 check_and_setup_lustre
44
45 cleanup_prepare () {
46
47     do_nodes $NODES_TO_USE "set $TRACE;
48 DIR=$TESTDIR/\\\$(hostname);
49 TESTFILE=\\\$DIR/$FILE;
50 rm -f \\\$TESTFILE;
51 rm -f $SUMFILE;
52 rmdir \\\$DIR 2>/dev/null;
53 mkdir -p \\\$DIR" || return ${PIPESTATUS[0]}
54     return 0;
55 }
56
57 do_mknod () {
58     echo "Creating file(s) by mknod (2) ... "
59
60     do_nodes $NODES_TO_USE "set $TRACE;
61 TESTFILE=$TESTDIR/\\\$(hostname)/$FILE;
62 mcreate \\\$TESTFILE; " || return ${PIPESTATUS[0]}
63     return 0
64 }
65
66 do_write () {
67     do_nodes $NODES_TO_USE "set $TRACE;
68 TESTFILE=$TESTDIR/\\\$(hostname)/$FILE;
69 dd if=/dev/zero of=\\\$TESTFILE bs=$FILE_SIZE count=1 2>/dev/null || exit 54;
70 echo \\\$(hostname) | dd of=\\\$TESTFILE conv=notrunc 2>/dev/null || exit 55; 
71 md5sum \\\$TESTFILE >> $SUMFILE; " || return ${PIPESTATUS[0]}
72     return 0
73 }
74
75 do_check_data () {
76     echo "Checking file(s) data ... md5sum : "
77     cat $SUMFILE
78
79     do_nodesv $NODES_TO_USE "md5sum --check $SUMFILE" || \
80         return ${PIPESTATUS[0]}
81     return 0
82 }
83
84 do_truncate () {
85     echo "Truncating file(s) ... "
86
87      do_nodes $NODES_TO_USE "set $TRACE;
88 TESTFILE=$TESTDIR/\\\$(hostname)/$FILE;
89 truncate \\\$TESTFILE 0" || return ${PIPESTATUS[0]} 
90
91     FILE_SIZE=0
92     return 0
93 }
94
95 # check st_uid, st_gid, st_size, st_mode
96 get_stat () {
97     local attr="$test_UID $test_GID $FILE_SIZE $CURRENT_MODE"
98
99     echo "Checking file(s) attributes ... "
100
101     do_nodesv $NODES_TO_USE "set $TRACE;
102 for HOST in ${NODES_TO_USE//,/ } ; do 
103     TESTFILE=$TESTDIR/\\\$HOST/$FILE;
104     tmp=\\\$(stat -c \\\"%u %g %s 0%a\\\" \\\$TESTFILE);
105     echo \\\"\\\$TESTFILE [ uid gid size mode ] expected : $attr ;  got : \\\$tmp \\\";
106     if [ x\\\"\\\$tmp\\\" != x\\\"$attr\\\" ] ; then
107         echo \\\"Wrong file attributes\\\";
108         exit 56;
109     fi;
110 done " || return ${PIPESTATUS[0]}
111     return 0 
112 }
113
114 do_chmod () {
115     echo "Performing chmod 0$NEW_MODE ..."
116
117     do_nodes $NODES_TO_USE "set $TRACE;
118 TESTFILE=$TESTDIR/\\\$(hostname)/$FILE;
119 chmod $NEW_MODE \\\$TESTFILE" || return ${PIPESTATUS[0]}
120  
121     CURRENT_MODE=$NEW_MODE
122     return 0
123 }
124
125 do_change_timestamps () {
126     echo "Changing atime, mtime ..."
127
128     do_nodes $NODES_TO_USE " set $TRACE;
129 TESTFILE=$TESTDIR/\\\$(hostname)/$FILE;
130 touch -c --date=\\\"$NEW_ATIME\\\" -a \\\$TESTFILE;
131 touch -c --date=\\\"$NEW_MTIME\\\" -m \\\$TESTFILE " || return ${PIPESTATUS[0]}
132     return 0
133 }
134
135 # check st_atime, st_mtime
136 do_check_timestamps () {
137     local atime=$(date --date="$NEW_ATIME" +%s)
138     local mtime=$(date --date="$NEW_MTIME" +%s)
139
140     local times="$atime $mtime"
141
142     echo "Checking atime, mtime ... "
143
144     do_nodesv $NODES_TO_USE "set $TRACE;
145 for HOST in ${NODES_TO_USE//,/ } ; do 
146     TESTFILE=$TESTDIR/\\\$HOST/$FILE;
147     tmp=\\\$(stat -c \\\"%X %Y\\\" \\\$TESTFILE);
148     if [ x\\\"\\\$tmp\\\" != x\\\"$times\\\" ] ; then
149        echo \\\"\\\$TESTFILE [ atime mtime ] expected : $times ;  got : \\\$tmp \\\";
150        RC=57;
151     fi;
152 done;
153 exit \\\$RC" || return ${PIPESTATUS[0]}
154     return 0 
155 }
156
157 do_fill_dir () {
158     echo "Filling up directories ... files : f1 ... f$NUM_FILES) ... "
159
160     do_nodes $NODES_TO_USE "set $TRACE;
161 TESTFILE=$TESTDIR/\\\$(hostname)/$FILE;
162 rm -f \\\$TESTFILE;
163 DIR=$TESTDIR/\\\$(hostname);
164 for i in \\\$(seq $NUM_FILES) ; do
165     touch \\\$DIR/f\\\$i;
166 done " || return ${PIPESTATUS[0]}
167     return 0
168 }
169
170 check_dir_contents () {
171     local num_files=${1:-1}
172
173     echo "Checking dir contents ... (should exist files : f$num_files ... f$NUM_FILES) ... "
174     do_nodes $NODES_TO_USE "set $TRACE;
175 for HOST in ${NODES_TO_USE//,/ } ; do 
176     DIR=$TESTDIR/\\\$HOST;
177     for i in \\\$(seq $NUM_FILES -1 $num_files) ; do
178         if ! [ -f \\\$DIR/f\\\$i ] ; then
179             echo \\\"ERROR: file \\\$DIR/f\\\$i should exist\\\";
180             RC=1;
181         fi;
182     done;
183     for i in \\\$(seq $(($num_files - 1 ))) ; do
184         if [ -f \\\$DIR/f\\\$i ] ; then
185             echo \\\"ERROR: deleted file \\\$DIR/f\\\$i exists\\\";
186             RC=1;
187         fi;
188     done;
189 done;
190 exit \\\$RC " || return ${PIPESTATUS[0]}
191     return 0
192 }
193
194 do_partial_delete () {
195     local num_files=$1
196
197     echo "Deleting files ... f1 ... f$num_files ... "
198     do_nodes $NODES_TO_USE "set $TRACE;
199 DIR=$TESTDIR/\\\$(hostname);
200 for i in \\\$(seq $num_files) ; do
201     if ! rm -f \\\$DIR/f\\\$i ; then
202         exit 1;
203     fi;
204 done " || return ${PIPESTATUS[0]}
205     return 0
206 }
207
208 STATUS=0
209
210 chmod 0777 $MOUNT   || exit 1
211 mkdir -p $TESTDIR   || exit 1
212 chmod 0777 $TESTDIR || exit 1
213
214 cleanup_prepare     || error_exit "cleanup failed"
215
216 # create file(s) (mknod (2)), write data, check data, check file attributes
217 echo "Part 1. create file(s) (mknod (2)), write data, check data, check file attributes."
218 do_mknod              || error_exit "mknod failed"
219 echo "Writing data to file(s) ... store md5sum ... "
220 do_write              || error_exit "write data failed"
221 do_check_data         || error_exit "md5sum verification failed"
222 get_stat              || { error_noexit "attributes check failed" ; STATUS=1; }
223
224 # file(s) attributes modification
225 echo "Part 2. file(s) attributes modification."
226 do_chmod              || error_exit "chmod failed"
227 get_stat              || { error_noexit "wrong attributes after chmod"; STATUS=1; }
228
229 do_change_timestamps  || error_exit "timestamps change failed"
230 do_check_timestamps   || { error_noexit "wrong timestamps"; STATUS=1; }
231
232 # truncate file(s) to 0 size, check new file size
233 echo "Part 3. truncate file(s) to 0 size, check new file size."
234 do_truncate     || error_exit"truncate failed"
235 get_stat        || { error_noexit "wrong attributes after truncate"; STATUS=1; }
236
237 # directory content solidity
238 echo "Part 4. directory content solidity: fill up directory, check dir content, remove some files, check dir content."
239 do_fill_dir        || error_exit "dir creation failed"
240 check_dir_contents || { error_noexit "dir contents check failed"; STATUS=1; }
241
242 do_partial_delete $(($NUM_FILES / 2))      || error_exit "delete failed"
243 check_dir_contents $(($NUM_FILES / 2 + 1)) ||
244     { error_noexit "dir contents check after delete failed"; STATUS=1; }
245
246 # "write_disjoint" test
247 echo "Part 5. write_disjoint test: see lustre/tests/mpi/write_disjoint.c for details"
248 if [ -f "$WRITE_DISJOINT" ]; then
249     set $TRACE
250     MACHINEFILE=${MACHINEFILE:-$TMP/$(basename $0 .sh).machines}
251     generate_machine_file $NODES_TO_USE $MACHINEFILE
252     mpi_run -np $(get_node_count ${NODES_TO_USE//,/ }) -machinefile $MACHINEFILE \
253     $WRITE_DISJOINT -f $WRITE_DISJOINT_FILE -n $NUMLOOPS || STATUS=1
254 else
255     skip_env "$0 : write_disjoint not found "
256 fi
257
258 equals_msg `basename $0`: test complete, cleaning up
259 rm -rf $TESTDIR
260 rm -f $MACHINEFILE
261 check_and_cleanup_lustre
262 exit $STATUS