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