Whamcloud - gitweb
LU-427 test: Test failure on test suite lfsck
[fs/lustre-release.git] / lustre / tests / utime.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/tests/utime.c
37  *
38  * Simple test for validating mtime on a file create and set via utime.
39  */
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <fcntl.h>
46 #include <unistd.h>
47 #include <time.h>
48 #include <string.h>
49 #include <utime.h>
50 #include <errno.h>
51
52 void usage(char *prog)
53 {
54         fprintf(stderr, "usage: %s <filename> [-s <filename>]\n", prog);
55         exit(1);
56 }
57
58 int main(int argc, char *argv[])
59 {
60         long before_mknod, after_mknod;
61         const char *prog = argv[0];
62         const char *filename = argv[1];
63         char *secname = NULL;
64         struct utimbuf utb;
65         struct stat st, st2;
66         int rc;
67         int c;
68
69         while ((c = getopt(argc, argv, "s:")) != -1) {
70                 switch(c) {
71                 case 's':
72                         secname = optarg;
73                         break;
74                 default:
75                         usage(argv[0]);
76                 }
77         }
78         if (optind + 1 > argc)
79                 usage(argv[0]);
80
81         /* Adjust the before time back one second, because the kernel's
82          * CURRENT_TIME (lockless clock reading, used to set inode times)
83          * may drift against the do_gettimeofday() time (TSC-corrected and
84          * locked clock reading, used to return timestamps to user space).
85          * This means that the mknod time could be a second older than the
86          * before time, even for a local filesystem such as ext3.
87          */
88         before_mknod = time(0) - 1;
89         rc = mknod(filename, 0700, S_IFREG);
90         after_mknod = time(0);
91         if (rc && errno != EEXIST) {
92                 fprintf(stderr, "%s: mknod(%s) failed: rc %d: %s\n",
93                         prog, filename, errno, strerror(errno));
94                 return 2;
95         } else if (!rc) {
96                 rc = stat(filename, &st);
97                 if (rc) {
98                         fprintf(stderr, "%s: stat(%s) failed: rc %d: %s\n",
99                                 prog, filename, errno, strerror(errno));
100                         return 3;
101                 }
102
103                 if (st.st_mtime < before_mknod || st.st_mtime > after_mknod) {
104                         fprintf(stderr, "%s: bad mknod(%s) times %lu <= %lu <= "
105                                 "%lu false\n", prog, filename, before_mknod,
106                                 st.st_mtime, after_mknod);
107                         return 4;
108                 }
109
110                 printf("%s: good mknod times %lu%s <= %lu <= %lu for %s\n",
111                        prog, before_mknod, before_mknod == st.st_mtime ? "*":"",
112                        st.st_mtime, after_mknod, filename);
113
114                 if (secname) {
115                         sleep(1);
116                         rc = stat(secname, &st2);
117                         if (rc) {
118                                 fprintf(stderr, "%s: stat(%s) failed: rc %d: "
119                                         "%s\n", prog, secname, errno,
120                                         strerror(errno));
121                                 return 5;
122                         }
123
124                         if (st2.st_mtime < before_mknod || 
125                             st2.st_mtime > after_mknod) {
126                                 fprintf(stderr, "%s: bad mknod(%s) times %lu "
127                                         " <= %lu <= %lu false\n", prog,
128                                         filename, before_mknod, st2.st_mtime,
129                                         after_mknod);
130                                 return 6;
131                         }
132
133                         printf("%s: good mknod times %lu%s <= %lu <= %lu "
134                                "for %s\n", prog, before_mknod, 
135                                before_mknod == st.st_mtime ? "*":"", 
136                                st2.st_mtime, after_mknod, secname);
137                 }
138         }
139
140         utb.actime = 200000;
141         utb.modtime = 100000;
142         rc = utime(filename, &utb);
143         if (rc) {
144                 fprintf(stderr, "%s: utime(%s) failed: rc %d: %s\n",
145                         prog, filename, errno, strerror(errno));
146                 return 7;
147         }
148         
149         rc = stat(filename, &st);
150         if (rc) {
151                 fprintf(stderr, "%s: second stat(%s) failed: rc %d: %s\n",
152                         prog, filename, errno, strerror(errno));
153                 return 8;
154         }
155
156         if (st.st_mtime != utb.modtime ) {
157                 fprintf(stderr, "%s: bad utime mtime(%s) %lu should be %lu\n",
158                         prog, filename, st.st_mtime, utb.modtime);
159                 return 9;
160         }
161
162         if (st.st_atime != utb.actime ) {
163                 fprintf(stderr, "%s: bad utime atime(%s) %lu should be %lu\n",
164                         prog, filename, st.st_atime, utb.actime);
165                 return 10;
166         }
167
168         printf("%s: good utime mtimes %lu, atime %lu\n",
169                prog, utb.modtime, utb.actime);
170
171         if (secname == NULL)
172                 return 0;
173         
174         /* Checking that times in past get updated on another client. */
175         rc = stat(secname, &st2);
176         if (rc) {
177                 fprintf(stderr, "%s: second stat(%s) failed: rc %d: %s\n",
178                         prog, secname, errno, strerror(errno));
179                 return 12;
180         }
181
182         if (st2.st_mtime != st.st_mtime) {
183                 fprintf(stderr, "%s: not synced mtime(%s) between clients: "
184                         "%lu should be %lu\n", prog, secname,
185                         st2.st_mtime, st.st_mtime);
186                 return 13;
187         }
188
189         if (st2.st_ctime != st.st_ctime) {
190                 fprintf(stderr, "%s: not synced ctime(%s) between clients: "
191                         "%lu should be %lu\n", prog, secname,
192                         st2.st_ctime, st.st_ctime);
193                 return 14;
194         }
195         
196         printf("%s: updated times for %s\n", prog, secname);
197         
198         return 0;
199 }