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 }