Mercurial > illumos > onarm
annotate usr/src/cmd/addbadsec/addbadsec.c @ 4:1a15d5aaf794
synchronized with onnv_86 (6202) in onnv-gate
author | Koji Uno <koji.uno@sun.com> |
---|---|
date | Mon, 31 Aug 2009 14:38:03 +0900 |
parents | c9caec207d52 |
children |
rev | line source |
---|---|
0 | 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, Version 1.0 only | |
6 * (the "License"). You may not use this file except in compliance | |
7 * with the License. | |
8 * | |
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE | |
10 * or http://www.opensolaris.org/os/licensing. | |
11 * See the License for the specific language governing permissions | |
12 * and limitations under the License. | |
13 * | |
14 * When distributing Covered Code, include this CDDL HEADER in each | |
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. | |
16 * If applicable, add the following below this CDDL HEADER, with the | |
17 * fields enclosed by brackets "[]" replaced with your own identifying | |
18 * information: Portions Copyright [yyyy] [name of copyright owner] | |
19 * | |
20 * CDDL HEADER END | |
21 */ | |
22 /* | |
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. | |
24 * Use is subject to license terms. | |
25 */ | |
26 | |
27 /* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */ | |
28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */ | |
29 /* All Rights Reserved */ | |
30 | |
31 /* | |
32 * Copyrighted as an unpublished work. | |
33 * (c) Copyright INTERACTIVE Systems Corporation 1986, 1988, 1990 | |
34 * All rights reserved. | |
35 */ | |
36 | |
4
1a15d5aaf794
synchronized with onnv_86 (6202) in onnv-gate
Koji Uno <koji.uno@sun.com>
parents:
0
diff
changeset
|
37 #pragma ident "%Z%%M% %I% %E% SMI" |
0 | 38 |
39 #include <stdio.h> | |
40 #include <fcntl.h> | |
41 #include <memory.h> | |
42 #include <sys/types.h> | |
43 #include <sys/param.h> | |
44 #include <sys/stat.h> | |
45 #include <sys/mkdev.h> | |
46 #include <sys/vtoc.h> | |
47 #include <sys/dkio.h> | |
48 #include <errno.h> | |
49 #include <sys/scsi/generic/commands.h> | |
50 #include <sys/scsi/impl/commands.h> | |
51 #include <sys/scsi/impl/uscsi.h> | |
52 #include "badsec.h" | |
53 | |
54 char *devname; /* name of device */ | |
55 int devfd; /* device file descriptor */ | |
56 struct dk_geom dkg; /* geometry */ | |
57 struct vtoc vtoc; /* table of contents */ | |
58 char *progname; | |
59 | |
60 extern struct badsec_lst *badsl_chain; | |
61 extern int badsl_chain_cnt; | |
62 extern struct badsec_lst *gbadsl_chain; | |
63 extern int gbadsl_chain_cnt; | |
64 | |
65 int alts_fd; | |
66 | |
67 static void giveusage(void); | |
68 static void rd_gbad(FILE *badsecfd); | |
69 static void add_gbad(int badsec_entry); | |
70 | |
71 int | |
72 main(int argc, char *argv[]) | |
73 { | |
74 extern int optind; | |
75 extern char *optarg; | |
76 | |
77 static char options[] = "Ipa:f:"; | |
78 char numbuf[100]; | |
79 char *nxtarg; | |
80 char *alts_name; | |
81 minor_t minor_val; | |
82 struct stat statbuf; | |
83 struct partition *part = NULL; | |
84 int alts_slice = -1; | |
85 int l; | |
86 int p; | |
87 int init_flag = 0; | |
88 int print_flag = 0; | |
89 int c; | |
90 int i; | |
91 FILE *badsecfd = NULL; | |
92 struct badsec_lst *blc_p; | |
93 | |
94 progname = argv[0]; | |
95 while ( (c=getopt(argc, argv, options)) != EOF ) { | |
96 switch (c) { | |
97 case 'I': | |
98 init_flag = 1; | |
99 break; | |
100 case 'p': | |
101 print_flag = 1; | |
102 break; | |
103 case 'a': | |
104 nxtarg = optarg; | |
105 for (;*nxtarg != '\0';) | |
106 add_gbad(strtol(nxtarg, &nxtarg, 0)); | |
107 break; | |
108 case 'f': | |
109 if ((badsecfd = fopen(optarg, "r")) == NULL) { | |
110 fprintf(stderr, "%s: unable to open %s file\n", progname, optarg); | |
111 exit(1); | |
112 } | |
113 break; | |
114 default: | |
115 giveusage(); | |
116 exit(2); | |
117 } | |
118 } | |
119 | |
120 /* get the last argument -- device stanza */ | |
121 if (argc != optind+1) { | |
122 fprintf(stderr, "Missing disk device name\n"); | |
123 giveusage(); | |
124 exit(3); | |
125 } | |
126 devname = argv[optind]; | |
127 | |
128 if (stat(devname, &statbuf)) { | |
129 fprintf(stderr, "%s: invalid device %s, stat failed\n", progname, devname); | |
130 giveusage(); | |
131 exit(4); | |
132 } | |
133 if ((statbuf.st_mode & S_IFMT) != S_IFCHR) { | |
134 fprintf(stderr, "%s: device %s is not character special\n", progname, devname); | |
135 giveusage(); | |
136 exit(5); | |
137 } | |
138 minor_val = minor(statbuf.st_rdev); | |
139 /* | |
140 * NEED A DEFINE FOR THE PHYSICAL BIT (0x10) | |
141 */ | |
142 if ((minor_val & 0x10) == 0) { | |
143 fprintf(stderr, "%s: device %s is not a physical slice\n", progname, devname); | |
144 giveusage(); | |
145 exit(6); | |
146 } | |
147 if ((minor_val % V_NUMPAR) != 0) { | |
148 fprintf(stderr, "%s: device %s is not a slice 0 device\n", progname, devname); | |
149 giveusage(); | |
150 exit(7); | |
151 } | |
152 if ((devfd=open(devname, O_RDWR)) == -1) { | |
153 fprintf(stderr, "%s: open of %s failed\n", progname ,devname); | |
154 perror(""); | |
155 exit(8); | |
156 } | |
157 if ((ioctl (devfd, DKIOCGGEOM, &dkg)) == -1) { | |
158 fprintf(stderr, "%s: unable to get disk geometry.\n", progname); | |
159 perror(""); | |
160 exit(9); | |
161 } | |
162 | |
163 if (ioctl(devfd, DKIOCGVTOC, &vtoc) == -1) | |
164 { | |
165 fprintf(stderr, "%s: could not get VTOC.\n", progname); | |
166 giveusage(); | |
167 exit(14); | |
168 } | |
169 | |
170 if ((vtoc.v_sanity != VTOC_SANE) || (vtoc.v_version != V_VERSION)) { | |
171 fprintf(stderr, "%s: invalid VTOC found.\n", progname); | |
172 giveusage(); | |
173 exit(15); | |
174 } | |
175 if (badsecfd) | |
176 rd_gbad(badsecfd); | |
177 | |
178 #ifdef ADDBAD_DEBUG | |
179 printf("\n main: Total bad sectors found= %d\n", gbadsl_chain_cnt); | |
180 for (blc_p=gbadsl_chain; blc_p; blc_p=blc_p->bl_nxt) { | |
181 for (i=0; i<blc_p->bl_cnt; i++) | |
182 printf(" badsec=%d ", blc_p->bl_sec[i]); | |
183 } | |
184 printf("\n"); | |
185 #endif | |
186 #ifdef PPP | |
187 /* | |
188 * If init_flag is set, run to completion. | |
189 */ | |
190 if (gbadsl_chain_cnt == 0 && init_flag == 0) | |
191 /* | |
192 * No defects and not initializing | |
193 */ | |
194 exit (0); | |
195 #endif | |
196 if (gbadsl_chain_cnt != 0) | |
197 { | |
198 if (try_hw_remap () == SUCCESS) | |
199 exit (0); | |
200 } | |
201 /* | |
202 * get ALTS slice | |
203 */ | |
204 for (i = 0; i < V_NUMPAR && alts_slice == -1; i++) | |
205 { | |
206 if (vtoc.v_part[i].p_tag == V_ALTSCTR) | |
207 { | |
208 alts_slice = i; | |
209 part = &vtoc.v_part[i]; | |
210 } | |
211 } | |
212 if (alts_slice == -1) | |
213 { | |
214 fprintf(stderr, "%s: No alternates slice.\n", progname); | |
215 exit(16); | |
216 } | |
217 l = strlen (devname); | |
218 sprintf (numbuf, "%d", alts_slice); | |
219 p = strlen (numbuf); | |
220 alts_name = (char *)malloc (l + p); | |
221 strcpy (alts_name, devname); | |
222 alts_name[l - 2] = 's'; | |
223 strcpy (&alts_name[l - 1], numbuf); | |
224 alts_name[l + p - 1] = '\0'; | |
225 if ((alts_fd=open(alts_name, O_RDWR)) == -1) { | |
226 fprintf(stderr, "%s: open of %s failed\n", progname ,alts_name); | |
227 perror(""); | |
228 exit(9); | |
229 } | |
230 if (print_flag) | |
231 { | |
232 print_altsec (part); | |
233 exit (0); | |
234 } | |
235 updatebadsec(part, init_flag); | |
236 wr_altsctr(); | |
237 | |
238 if (ioctl(devfd, DKIOCADDBAD, NULL) == -1) { | |
239 fprintf(stderr, "Warning: DKIOCADDBAD io control failed. System must be re-booted\n"); | |
240 fprintf(stderr, "for alternate sectors to be usable.\n"); | |
241 exit(17); | |
242 } | |
243 sync(); | |
244 | |
245 fclose(badsecfd); | |
246 close (alts_fd); | |
247 close (devfd); | |
248 return(0); | |
249 } | |
250 | |
251 /* | |
252 * Giveusage () | |
253 * Give a (not so) concise message on how to use this program. | |
254 */ | |
255 static | |
256 void giveusage(void) | |
257 { | |
258 fprintf(stderr, "%s [-p] [-a sector] [-f filename] raw-device\n", progname); | |
259 fprintf(stderr, " p - Print existing bad block map\n"); | |
260 fprintf(stderr, " a - Add the given sectors to the bad block list\n"); | |
261 fprintf(stderr, " f - Add the sectors from <filename> to the bad block list\n"); | |
262 if (devfd) | |
263 close(devfd); | |
264 } | |
265 | |
266 | |
267 /* | |
268 * read in the additional growing bad sectors | |
269 */ | |
270 static void | |
271 rd_gbad(FILE *badsecfd) | |
272 { | |
273 int badsec_entry; | |
274 int status; | |
275 | |
276 status = fscanf(badsecfd, "%d", &badsec_entry); | |
277 while (status!=EOF) { | |
278 add_gbad(badsec_entry); | |
279 status = fscanf(badsecfd, "%d", &badsec_entry); | |
280 } | |
281 } | |
282 | |
283 static void | |
284 add_gbad(int badsec_entry) | |
285 { | |
286 struct badsec_lst *blc_p; | |
287 | |
288 if (!gbadsl_chain) { | |
289 blc_p = (struct badsec_lst *)malloc(BADSLSZ); | |
290 if (!blc_p) { | |
291 fprintf(stderr, "Unable to allocate memory for additional bad sectors\n"); | |
292 exit(18); | |
293 } | |
294 gbadsl_chain = blc_p; | |
295 blc_p->bl_cnt = 0; | |
296 blc_p->bl_nxt = 0; | |
297 } | |
298 for (blc_p = gbadsl_chain; blc_p->bl_nxt; ) | |
299 blc_p = blc_p->bl_nxt; | |
300 | |
301 if (blc_p->bl_cnt == MAXBLENT) { | |
302 blc_p->bl_nxt = (struct badsec_lst *)malloc(BADSLSZ); | |
303 if (!blc_p->bl_nxt) { | |
304 fprintf(stderr, "Unable to allocate memory for additional bad sectors\n"); | |
305 exit(19); | |
306 } | |
307 blc_p = blc_p->bl_nxt; | |
308 blc_p->bl_cnt = 0; | |
309 blc_p->bl_nxt = 0; | |
310 } | |
311 blc_p->bl_sec[blc_p->bl_cnt++] = badsec_entry; | |
312 gbadsl_chain_cnt++; | |
313 } | |
314 | |
315 /* | |
316 * Map a block using hardware (SCSI) techniques. | |
317 */ | |
318 /*ARGSUSED*/ | |
319 int | |
320 hardware_remap (bn) | |
321 int bn; | |
322 { | |
323 u_int byte_swap_32 (u_int); | |
324 u_short byte_swap_16 (u_short); | |
325 | |
326 struct uscsi_cmd ucmd; | |
327 union scsi_cdb cdb; | |
328 struct scsi_reassign_blk defect_list; | |
329 | |
330 /* | |
331 * Build and execute the uscsi ioctl | |
332 */ | |
333 (void) memset((char *)&ucmd, 0, sizeof (ucmd)); | |
334 (void) memset((char *)&cdb, 0, sizeof (union scsi_cdb)); | |
335 (void) memset((char *)&defect_list, 0, | |
336 sizeof (struct scsi_reassign_blk)); | |
337 cdb.scc_cmd = SCMD_REASSIGN_BLOCK; | |
338 ucmd.uscsi_cdb = (caddr_t) &cdb; | |
339 ucmd.uscsi_cdblen = CDB_GROUP0; | |
340 ucmd.uscsi_bufaddr = (caddr_t) &defect_list; | |
341 ucmd.uscsi_buflen = sizeof (struct scsi_reassign_blk); | |
342 defect_list.length = byte_swap_16 (sizeof (defect_list.defect)); | |
343 defect_list.defect = byte_swap_32 (bn); | |
344 /* | |
345 printf ("length - %x %x\n", sizeof (defect_list.defect), defect_list.length); | |
346 printf ("defect - %x %x\n", bn, defect_list.defect); | |
347 */ | |
348 /* | |
349 * Set function flags for driver. | |
350 */ | |
351 ucmd.uscsi_flags = USCSI_ISOLATE | USCSI_DIAGNOSE | USCSI_SILENT; | |
352 ucmd.uscsi_timeout = 30; /* 30 seconds */ | |
353 | |
354 /* | |
355 * Execute the ioctl | |
356 */ | |
357 if (ioctl(devfd, USCSICMD, &ucmd) == -1) | |
358 { | |
359 if (errno != ENOTTY) | |
360 { | |
361 perror ("SCSI hardware re-assign failed"); | |
362 /* | |
363 * It looks like a failure but by returning success | |
364 * the upper layer will not try to do | |
365 * software remapping. | |
366 */ | |
367 return (SUCCESS); | |
368 } | |
369 return (FAILURE); | |
370 } | |
371 return (SUCCESS); | |
372 } | |
373 | |
374 u_int | |
375 byte_swap_32 (u_int nav) | |
376 { | |
377 u_int rc; | |
378 rc = ((nav & 0xff000000) >> 24) | ((nav & 0x00ff0000) >> 8) | | |
379 ((nav & 0x0000ff00) << 8) | ((nav & 0x000000ff) << 24); | |
380 return (rc); | |
381 } | |
382 | |
383 u_short | |
384 byte_swap_16 (u_short niv) | |
385 { | |
386 u_short rc; | |
387 rc = (u_short)((int)(niv & 0xff00) >> 8) | ((niv & 0x00ff) << 8); | |
388 return (rc); | |
389 } | |
390 | |
391 int | |
392 try_hw_remap () | |
393 { | |
394 struct badsec_lst *blc_p; | |
395 int i; | |
396 | |
397 for (blc_p = gbadsl_chain; blc_p != 0; blc_p = blc_p->bl_nxt) | |
398 { | |
399 | |
400 for (i = 0; i < blc_p->bl_cnt; i++) | |
401 if (hardware_remap (blc_p->bl_sec[i]) == FAILURE) | |
402 return (FAILURE); | |
403 } | |
404 return (SUCCESS); | |
405 } |