1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2013 Damian Bogel.  All rights reserved.
  14  */
  15 
  16 #include <libfsd.h>
  17 #include <stdio.h>
  18 #include <stdlib.h>
  19 
  20 /*
  21  * Examples of usage:
  22  * fsdadm -m /mnt -c 15 -l 1 200        15% read less 1 to 200 for /mnt
  23  * fsdadm -n -c 50 -l 1 10      50% read less of 1 to 10ms for every new mount
  24  * fsdadm -m /mnt -x            clear all disturbances for /mnt
  25  * fsdadm -n -x                 clear all disturbances for every new mount
  26  */
  27 
  28 #define READ_LESS       0
  29 #define OPS_NUM         1
  30 
  31 int clear;
  32 int disable;
  33 int enable;
  34 int newmount;
  35 int options[OPS_NUM];
  36 
  37 int
  38 main(int argc, char *argv[])
  39 {
  40         extern char *optarg;
  41         extern int optind;
  42 
  43         char *mnt = NULL;
  44         int fd;
  45         int opt;
  46         int error;
  47         fsd_stat_t stat;
  48 
  49         while ((opt = getopt(argc, argv, "edm:c:l:xn")) != -1)
  50                 switch (opt) {
  51                 case 'e':
  52                         enable = 1;
  53                         break;
  54 
  55                 case 'd':
  56                         disable = 1;
  57                         break;
  58 
  59                 case 'c':
  60                         stat.fsds_read_less_chance = atoi(optarg);
  61                         break;
  62 
  63                 case 'm':
  64                         mnt = optarg;
  65                         break;
  66 
  67                 case 'l':
  68                         options[READ_LESS] = 1;
  69                         if (optind > argc - 1) {
  70                                 (void) fprintf(stderr,
  71                                     "Error: -l requires two arguments\n");
  72                                 return (1);
  73                         }
  74                         stat.fsds_read_less_r[0] = atoi(argv[optind-1]);
  75                         stat.fsds_read_less_r[1] = atoi(argv[optind]);
  76                         break;
  77 
  78                 case 'x':
  79                         clear = 1;
  80                         break;
  81 
  82                 case 'n':
  83                         newmount = 1;
  84                         break;
  85 
  86                 case '?':
  87                         (void) fprintf(stderr,
  88                             "Error: Unrecognized option: "
  89                             "-%c\n", optopt);
  90                         return (1);
  91                 }
  92 
  93         fd = fsd_open();
  94         if (fd == -1) {
  95                 (void) fprintf(stderr, "Error: Cannot open fsd device.\n");
  96                 return (1);
  97         }
  98 
  99         error = 0;
 100         if (enable) {
 101                 if (fsd_enable(fd))
 102                         error = fsd_errno;
 103         } else if (disable) {
 104                 if (fsd_disable(fd))
 105                         error = fsd_errno;
 106         } else {
 107                 if (newmount) {
 108                         if (clear) {
 109                                 if (fsd_newdisturb_off(fd))
 110                                         error = fsd_errno;
 111                         } else {
 112                                 if (fsd_newdisturb(fd, &stat))
 113                                         error = fsd_errno;
 114                         }
 115                 } else {
 116                         if (clear) {
 117                                 if (fsd_disturb_off(fd, mnt))
 118                                         error = fsd_errno;
 119                         } else {
 120                                 if (fsd_disturb(fd, mnt, &stat))
 121                                         error = fsd_errno;
 122                         }
 123                 }
 124         }
 125 
 126         fsd_close(fd);
 127         if (error) {
 128                 (void) fprintf(stderr, "Error: %s\n", fsd_strerr(error));
 129                 return (1);
 130         }
 131         return (0);
 132 }