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