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