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