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