8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / addbadsec / addbadsec.c
blobd03f0ce1b9fdd1c1463d6504c95280fd84aca3c0
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 /* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
28 /* All Rights Reserved */
31 * Copyrighted as an unpublished work.
32 * (c) Copyright INTERACTIVE Systems Corporation 1986, 1988, 1990
33 * All rights reserved.
36 #include <stdio.h>
37 #include <fcntl.h>
38 #include <memory.h>
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <sys/stat.h>
42 #include <sys/mkdev.h>
43 #include <sys/vtoc.h>
44 #include <sys/dkio.h>
45 #include <errno.h>
46 #include <stdlib.h>
47 #include <strings.h>
48 #include <unistd.h>
49 #include <stropts.h>
50 #include <sys/scsi/generic/commands.h>
51 #include <sys/scsi/impl/commands.h>
52 #include <sys/scsi/impl/uscsi.h>
53 #include "badsec.h"
55 char *devname; /* name of device */
56 int devfd; /* device file descriptor */
57 struct dk_geom dkg; /* geometry */
58 struct extvtoc vtoc; /* table of contents */
59 char *progname;
61 extern struct badsec_lst *badsl_chain;
62 extern int badsl_chain_cnt;
63 extern struct badsec_lst *gbadsl_chain;
64 extern int gbadsl_chain_cnt;
65 extern int print_altsec(struct extpartition *);
66 extern int updatebadsec(struct extpartition *, int);
67 extern void wr_altsctr(void);
69 int alts_fd;
71 static void giveusage(void);
72 static void rd_gbad(FILE *badsecfd);
73 static void add_gbad(int badsec_entry);
74 static int try_hw_remap(void);
75 static int hardware_remap(blkaddr_t);
77 int
78 main(int argc, char *argv[])
80 extern int optind;
81 extern char *optarg;
83 static char options[] = "Ipa:f:";
84 char numbuf[100];
85 char *nxtarg;
86 char *alts_name;
87 minor_t minor_val;
88 struct stat statbuf;
89 struct extpartition *part = NULL;
90 int alts_slice = -1;
91 int l;
92 int p;
93 int init_flag = 0;
94 int print_flag = 0;
95 int c;
96 int i;
97 FILE *badsecfd = NULL;
99 progname = argv[0];
100 while ((c = getopt(argc, argv, options)) != EOF) {
101 switch (c) {
102 case 'I':
103 init_flag = 1;
104 break;
105 case 'p':
106 print_flag = 1;
107 break;
108 case 'a':
109 nxtarg = optarg;
110 for (; *nxtarg != '\0'; )
111 add_gbad(strtol(nxtarg, &nxtarg, 0));
112 break;
113 case 'f':
114 if ((badsecfd = fopen(optarg, "r")) == NULL) {
115 (void) fprintf(stderr,
116 "%s: unable to open %s file\n",
117 progname, optarg);
118 exit(1);
120 break;
121 default:
122 giveusage();
123 exit(2);
127 /* get the last argument -- device stanza */
128 if (argc != optind+1) {
129 (void) fprintf(stderr, "Missing disk device name\n");
130 giveusage();
131 exit(3);
133 devname = argv[optind];
135 if (stat(devname, &statbuf)) {
136 (void) fprintf(stderr, "%s: invalid device %s, stat failed\n",
137 progname, devname);
138 giveusage();
139 exit(4);
141 if ((statbuf.st_mode & S_IFMT) != S_IFCHR) {
142 (void) fprintf(stderr, "%s: device %s is not character"
143 " special\n", progname, devname);
144 giveusage();
145 exit(5);
147 minor_val = minor(statbuf.st_rdev);
149 * NEED A DEFINE FOR THE PHYSICAL BIT (0x10)
151 if ((minor_val & 0x10) == 0) {
152 (void) fprintf(stderr, "%s: device %s is not a physical"
153 " slice\n", progname, devname);
154 giveusage();
155 exit(6);
157 if ((minor_val % V_NUMPAR) != 0) {
158 (void) fprintf(stderr, "%s: device %s is not a slice 0"
159 " device\n", progname, devname);
160 giveusage();
161 exit(7);
163 if ((devfd = open(devname, O_RDWR)) == -1) {
164 (void) fprintf(stderr, "%s: open of %s failed\n",
165 progname, devname);
166 perror("");
167 exit(8);
169 if ((ioctl(devfd, DKIOCGGEOM, &dkg)) == -1) {
170 (void) fprintf(stderr, "%s: unable to get disk geometry.\n",
171 progname);
172 perror("");
173 exit(9);
176 if (ioctl(devfd, DKIOCGEXTVTOC, &vtoc) == -1) {
177 (void) fprintf(stderr, "%s: could not get VTOC.\n", progname);
178 giveusage();
179 exit(14);
182 if ((vtoc.v_sanity != VTOC_SANE) || (vtoc.v_version != V_VERSION)) {
183 (void) fprintf(stderr, "%s: invalid VTOC found.\n", progname);
184 giveusage();
185 exit(15);
187 if (badsecfd)
188 rd_gbad(badsecfd);
190 #ifdef ADDBAD_DEBUG
192 struct badsec_lst *blc_p;
193 printf("\n main: Total bad sectors found= %d\n", gbadsl_chain_cnt);
194 for (blc_p = gbadsl_chain; blc_p; blc_p = blc_p->bl_nxt) {
195 for (i = 0; i < blc_p->bl_cnt; i++)
196 printf(" badsec=%d ", blc_p->bl_sec[i]);
198 printf("\n");
200 #endif
201 #ifdef PPP
203 * If init_flag is set, run to completion.
205 if (gbadsl_chain_cnt == 0 && init_flag == 0)
207 * No defects and not initializing
209 exit(0);
210 #endif
211 if (gbadsl_chain_cnt != 0)
213 if (try_hw_remap() == SUCCESS)
214 exit(0);
217 * get ALTS slice
219 for (i = 0; i < V_NUMPAR && alts_slice == -1; i++)
221 if (vtoc.v_part[i].p_tag == V_ALTSCTR)
223 alts_slice = i;
224 part = &vtoc.v_part[i];
227 if (alts_slice == -1)
229 (void) fprintf(stderr, "%s: No alternates slice.\n", progname);
230 exit(16);
232 l = strlen(devname);
233 (void) sprintf(numbuf, "%d", alts_slice);
234 p = strlen(numbuf);
235 alts_name = (char *)malloc(l + p);
236 (void) strcpy(alts_name, devname);
237 alts_name[l - 2] = 's';
238 (void) strcpy(&alts_name[l - 1], numbuf);
239 alts_name[l + p - 1] = '\0';
240 if ((alts_fd = open(alts_name, O_RDWR)) == -1) {
241 (void) fprintf(stderr, "%s: open of %s failed\n",
242 progname, alts_name);
243 perror("");
244 exit(9);
246 if (print_flag)
248 (void) print_altsec(part);
249 exit(0);
251 (void) updatebadsec(part, init_flag);
252 wr_altsctr();
254 if (ioctl(devfd, DKIOCADDBAD, NULL) == -1) {
255 (void) fprintf(stderr, "Warning: DKIOCADDBAD io control"
256 " failed. System must be re-booted\n");
257 (void) fprintf(stderr, "for alternate sectors to be usable.\n");
258 exit(17);
260 sync();
262 (void) fclose(badsecfd);
263 (void) close(alts_fd);
264 (void) close(devfd);
265 return (0);
269 * Giveusage ()
270 * Give a (not so) concise message on how to use this program.
272 static void
273 giveusage(void)
275 (void) fprintf(stderr, "%s [-p] [-a sector] [-f filename]"
276 " raw-device\n", progname);
277 (void) fprintf(stderr, " p - Print existing bad block map\n");
278 (void) fprintf(stderr, " a - Add the given sectors to the"
279 " bad block list\n");
280 (void) fprintf(stderr, " f - Add the sectors from <filename>"
281 " to the bad block list\n");
282 if (devfd)
283 (void) close(devfd);
288 * read in the additional growing bad sectors
290 static void
291 rd_gbad(FILE *badsecfd)
293 int badsec_entry;
294 int status;
296 status = fscanf(badsecfd, "%d", &badsec_entry);
297 while (status != EOF) {
298 add_gbad(badsec_entry);
299 status = fscanf(badsecfd, "%d", &badsec_entry);
303 static void
304 add_gbad(int badsec_entry)
306 struct badsec_lst *blc_p;
308 if (!gbadsl_chain) {
309 blc_p = (struct badsec_lst *)malloc(BADSLSZ);
310 if (!blc_p) {
311 (void) fprintf(stderr, "Unable to allocate memory"
312 " for additional bad sectors\n");
313 exit(18);
315 gbadsl_chain = blc_p;
316 blc_p->bl_cnt = 0;
317 blc_p->bl_nxt = 0;
319 for (blc_p = gbadsl_chain; blc_p->bl_nxt; )
320 blc_p = blc_p->bl_nxt;
322 if (blc_p->bl_cnt == MAXBLENT) {
323 blc_p->bl_nxt = (struct badsec_lst *)malloc(BADSLSZ);
324 if (!blc_p->bl_nxt) {
325 (void) fprintf(stderr, "Unable to allocate memory"
326 " for additional bad sectors\n");
327 exit(19);
329 blc_p = blc_p->bl_nxt;
330 blc_p->bl_cnt = 0;
331 blc_p->bl_nxt = 0;
333 blc_p->bl_sec[blc_p->bl_cnt++] = badsec_entry;
334 gbadsl_chain_cnt++;
338 * Map a block using hardware (SCSI) techniques.
340 /*ARGSUSED*/
341 static int
342 hardware_remap(bn)
343 blkaddr_t bn;
345 uint_t byte_swap_32(uint_t);
346 ushort_t byte_swap_16(ushort_t);
348 struct uscsi_cmd ucmd;
349 union scsi_cdb cdb;
350 struct scsi_reassign_blk defect_list;
353 * Build and execute the uscsi ioctl
355 (void) memset((char *)&ucmd, 0, sizeof (ucmd));
356 (void) memset((char *)&cdb, 0, sizeof (union scsi_cdb));
357 (void) memset((char *)&defect_list, 0,
358 sizeof (struct scsi_reassign_blk));
359 cdb.scc_cmd = SCMD_REASSIGN_BLOCK;
360 ucmd.uscsi_cdb = (caddr_t)&cdb;
361 ucmd.uscsi_cdblen = CDB_GROUP0;
362 ucmd.uscsi_bufaddr = (caddr_t)&defect_list;
363 ucmd.uscsi_buflen = sizeof (struct scsi_reassign_blk);
364 defect_list.length = byte_swap_16(sizeof (defect_list.defect));
365 defect_list.defect = byte_swap_32(bn);
367 * Set function flags for driver.
369 ucmd.uscsi_flags = USCSI_ISOLATE | USCSI_DIAGNOSE | USCSI_SILENT;
370 ucmd.uscsi_timeout = 30; /* 30 seconds */
373 * Execute the ioctl
375 if (ioctl(devfd, USCSICMD, &ucmd) == -1)
377 if (errno != ENOTTY)
379 perror("SCSI hardware re-assign failed");
381 * It looks like a failure but by returning success
382 * the upper layer will not try to do
383 * software remapping.
385 return (SUCCESS);
387 return (FAILURE);
389 return (SUCCESS);
392 uint_t
393 byte_swap_32(uint_t nav)
395 uint_t rc;
396 rc = ((nav & 0xff000000) >> 24) | ((nav & 0x00ff0000) >> 8) |
397 ((nav & 0x0000ff00) << 8) | ((nav & 0x000000ff) << 24);
398 return (rc);
401 ushort_t
402 byte_swap_16(ushort_t niv)
404 ushort_t rc;
405 rc = (ushort_t)((int)(niv & 0xff00) >> 8) | ((niv & 0x00ff) << 8);
406 return (rc);
409 static int
410 try_hw_remap()
412 struct badsec_lst *blc_p;
413 int i;
415 for (blc_p = gbadsl_chain; blc_p != 0; blc_p = blc_p->bl_nxt) {
416 for (i = 0; i < blc_p->bl_cnt; i++)
417 if (hardware_remap(blc_p->bl_sec[i]) == FAILURE)
418 return (FAILURE);
420 return (SUCCESS);