1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * a program to open/create a named attribute file, write some data;
29 * then wait for recovery to continue reading back the written data.
30 */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <fcntl.h>
36 #include <sys/stat.h>
37 #include <sys/types.h>
38 #include <sys/errno.h>
39
40 #define BUFSIZE 1024
41
42 extern int errno;
43
44 void prnusage();
45 void cleanup();
46
47 int
48 main(int argc, char **argv)
49 {
50 char *filename = NULL;
51 char *donefile = NULL;
52 char *attrfile = "attribute";
53 char *wbuf = NULL;
54 char *rbuf = NULL;
55 int fd = -1;
56 int afd = -1;
57 int jfd = -1;
58 int i, c;
59
60 while ((c = getopt(argc, argv, "f:u:")) != EOF) {
61 switch (c) {
62 case 'f':
63 filename = optarg;
64 break;
65 case 'u':
66 donefile = optarg;
67 break;
68 case '?':
69 default:
70 prnusage(argv[0]);
71 }
72 }
73
74 if ((filename == NULL) || (*filename == '\0')) {
75 (void) fprintf(stderr,
76 "%s: No test filename specified\n", argv[0]);
77 prnusage(argv[0]);
78 }
79
80 if ((donefile == NULL) || (*donefile == '\0')) {
81 (void) fprintf(stderr,
82 "%s: No DONE filename specified\n", argv[0]);
83 prnusage(argv[0]);
84 }
85
86 (void) fprintf(stdout, "Testing starts: filename=%s, donefile=%s\n",
87 filename, donefile);
88
89 if ((fd = open(filename, O_CREAT|O_RDWR, 0777)) < 0) {
90 (void) fprintf(stderr,
91 "Failed to open file: <%s>", filename);
92 perror(" ");
93 exit(errno);
94 }
95 (void) fprintf(stdout, " open(%s) OK\n", filename);
96
97 /* build the write buffer for the file */
98 if ((wbuf = malloc(sizeof (char) * BUFSIZE)) == NULL) {
99 perror("malloc(wbuf)");
100 cleanup(fd, afd, wbuf, errno);
101 }
102 for (i = 0; i < BUFSIZE; i++)
103 wbuf[i] = (i % 26) + 'a';
104
105 if (write(fd, wbuf, BUFSIZE) < BUFSIZE) {
106 (void) fprintf(stderr,
107 "Failed to write to file: <%s>", filename);
108 perror(" ");
109 cleanup(fd, afd, wbuf, 2);
110 }
111 (void) fprintf(stdout, " write(%s) OK\n", filename);
112
113 afd = openat(fd, attrfile, O_CREAT | O_RDWR | O_XATTR, 0777);
114 if (afd < 0) {
115 (void) fprintf(stderr,
116 "Failed to openat <%s>\n, attrfile");
117 perror("openat(fd, \"attribute\", O_CREAT | O_RDWR | O_XATTR, "
118 "0777))");
119 cleanup(fd, afd, wbuf, errno);
120 }
121 (void) fprintf(stdout, " openat(%s) OK\n", attrfile);
122
123 if ((c = write(afd, wbuf, BUFSIZE)) < BUFSIZE) {
124 (void) fprintf(stderr,
125 "Failed to write to <%s> file", attrfile);
126 perror(" ");
127 cleanup(fd, afd, wbuf, 3);
128 }
129 (void) fprintf(stdout, " write(%s) OK\n", attrfile);
130
131 /* just to make sure data are written to be read */
132 if ((fsync(afd)) < 0) {
133 (void) fprintf(stderr,
134 "Failed to write to <%s> file", attrfile);
135 perror(" ");
136 cleanup(fd, afd, wbuf, 3);
137 }
138 (void) fprintf(stdout, " fsync(%s) OK\n", attrfile);
139
140 /* now let's wait for the recovery, and break after 5 min */
141 c = 0;
142 while ((jfd = open(donefile, O_RDONLY)) < 0) {
143 sleep(1);
144 c++;
145 if (c > 300) {
146 (void) fprintf(stdout,
147 " Failed to open(%s)\n", donefile);
148 (void) fprintf(stdout,
149 " problem with client recovery.\n");
150 exit(6);
151 }
152 }
153 if (jfd > 0)
154 close(jfd);
155 (void) fprintf(stdout, " open(%s) OK, server came back.\n", donefile);
156
157 /* and try to read-back the file data after we recovered */
158 if ((lseek(afd, 0, SEEK_SET)) < 0) {
159 (void) fprintf(stderr, "lseek(0) failed");
160 perror(" ");
161 cleanup(fd, afd, wbuf, 5);
162 }
163 (void) fprintf(stdout, " lseek(%s) OK\n", attrfile);
164
165 if ((rbuf = malloc(sizeof (char) * BUFSIZE)) == NULL) {
166 perror("malloc(rbuf)");
167 cleanup(fd, afd, wbuf, errno);
168 }
169
170 if ((c = read(afd, rbuf, BUFSIZE)) != BUFSIZE) {
171 (void) fprintf(stderr,
172 "Failed to read to attribute file after we are recover");
173 perror(" ");
174 (void) fprintf(stderr, "Only %d bytes read\n", c);
175 cleanup(fd, afd, wbuf, 2);
176 }
177 (void) fprintf(stdout, " read(%s) OK, read %d bytes\n", attrfile, c);
178
179 for (i = 0; i < BUFSIZE; i++) {
180 if (rbuf[i] != wbuf[i]) {
181 (void) fprintf(stderr,
182 "Failed to read the right pattern at %d; ", i);
183 (void) fprintf(stderr,
184 "expected=(%ll), got=(%ll)\n", wbuf[i], rbuf[i]);
185 if (rbuf != NULL)
186 free(rbuf);
187 cleanup(fd, afd, wbuf, i);
188 }
189 }
190 (void) fprintf(stdout, " comparing data OK, i=%d\n", i);
191 (void) fprintf(stdout, "GOOD, testing is successful.\n");
192
193 if (rbuf != NULL)
194 free(rbuf);
195
196 cleanup(fd, afd, wbuf, 0);
197
198 return (0);
199 }
200
201 void
202 prnusage(char *pname)
203 {
204 (void) fprintf(stderr,
205 "Usage: %s -f <filename> -u <DONE_reboot|DONE_reset file>\n",
206 pname);
207 exit(99);
208 }
209
210 void
211 cleanup(int fd, int afd, char *bufp, int exitcode)
212 {
213 if (fd != -1)
214 (void) close(fd);
215 if (afd != -1)
216 (void) close(afd);
217 if (bufp != NULL)
218 free(bufp);
219
220 exit(exitcode);
221 }