diff options
Diffstat (limited to 'usr/src')
42 files changed, 2139 insertions, 1094 deletions
diff --git a/usr/src/cmd/diskscan/diskscan.c b/usr/src/cmd/diskscan/diskscan.c index 4c311b37bf..0f9de773f4 100644 --- a/usr/src/cmd/diskscan/diskscan.c +++ b/usr/src/cmd/diskscan/diskscan.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -168,7 +168,7 @@ main(int argc, char *argv[]) { static void scandisk(char *device, int devfd, int writeflag) { - int trksiz = NBPSCTR * dkg.dkg_nsect; + int trksiz = 0; char *verbuf; diskaddr_t cursec; int cylsiz = dkg.dkg_nsect * dkg.dkg_nhead; @@ -176,6 +176,15 @@ scandisk(char *device, int devfd, int writeflag) char *rptr; diskaddr_t tmpend = 0; diskaddr_t tmpsec = 0; + struct dk_minfo mediainfo; + uint_t sector_size; + + if ((ioctl(devfd, DKIOCGMEDIAINFO, &mediainfo)) == 0) { + sector_size = mediainfo.dki_lbsize; + } else { + sector_size = NBPSCTR; + } + trksiz = sector_size * dkg.dkg_nsect; /* #define LIBMALLOC */ @@ -187,23 +196,25 @@ scandisk(char *device, int devfd, int writeflag) /* make track buffer sector aligned */ - if (mallopt(M_GRAIN, 0x200)) { + if (mallopt(M_GRAIN, sector_size)) { perror("mallopt"); exit(1); } - if ((verbuf = malloc(NBPSCTR * dkg.dkg_nsect)) == (char *)NULL) { + if ((verbuf = malloc(sector_size * dkg.dkg_nsect)) == + (char *)NULL) { perror("malloc"); exit(1); } #else - if ((verbuf = malloc(0x200 + NBPSCTR * dkg.dkg_nsect)) + if ((verbuf = malloc(sector_size + sector_size * dkg.dkg_nsect)) == (char *)NULL) { perror("malloc"); exit(1); } - verbuf = (char *)(((unsigned long)verbuf + 0x00000200) & 0xfffffe00); + verbuf = (char *)((((unsigned long)verbuf + sector_size)) & + (-sector_size)); #endif @@ -238,7 +249,7 @@ scandisk(char *device, int devfd, int writeflag) } for (cursec = 0; cursec < unix_size; cursec += dkg.dkg_nsect) { - if (llseek(devfd, cursec * NBPSCTR, 0) == -1) { + if (llseek(devfd, cursec * sector_size, 0) == -1) { (void) fprintf(stderr, "Error seeking sector %llu Cylinder %llu\n", cursec, cursec / cylsiz); @@ -261,7 +272,8 @@ scandisk(char *device, int devfd, int writeflag) * then announce the sector bad on stderr */ - if (llseek(devfd, tmpsec * NBPSCTR, 0) == -1) { + if (llseek(devfd, tmpsec * sector_size, + 0) == -1) { (void) fprintf(stderr, "Error seeking " "sector %llu Cylinder %llu\n", tmpsec, cursec / cylsiz); @@ -270,7 +282,8 @@ scandisk(char *device, int devfd, int writeflag) report("Writing", tmpsec); - if (write(devfd, verbuf, NBPSCTR) != NBPSCTR) { + if (write(devfd, verbuf, sector_size) + != sector_size) { (void) fprintf(stderr, "%llu\n", tmpsec + unix_base); numbadwr++; @@ -283,7 +296,7 @@ scandisk(char *device, int devfd, int writeflag) do_readonly: for (cursec = 0; cursec < unix_size; cursec += dkg.dkg_nsect) { - if (llseek(devfd, cursec * NBPSCTR, 0) == -1) { + if (llseek(devfd, cursec * sector_size, 0) == -1) { (void) fprintf(stderr, "Error seeking sector %llu Cylinder %llu\n", cursec, cursec / cylsiz); @@ -300,14 +313,16 @@ scandisk(char *device, int devfd, int writeflag) if (read(devfd, verbuf, trksiz) != trksiz) { tmpend = cursec + dkg.dkg_nsect; for (tmpsec = cursec; tmpsec < tmpend; tmpsec++) { - if (llseek(devfd, tmpsec * NBPSCTR, 0) == -1) { + if (llseek(devfd, tmpsec * sector_size, + 0) == -1) { (void) fprintf(stderr, "Error seeking" " sector %llu Cylinder %llu\n", tmpsec, cursec / cylsiz); verexit(1); } report("Reading", tmpsec); - if (read(devfd, verbuf, NBPSCTR) != NBPSCTR) { + if (read(devfd, verbuf, sector_size) != + sector_size) { (void) fprintf(stderr, "%llu\n", tmpsec + unix_base); numbadrd++; diff --git a/usr/src/cmd/fdisk/fdisk.c b/usr/src/cmd/fdisk/fdisk.c index 6a0447bbcd..e20bea17ad 100644 --- a/usr/src/cmd/fdisk/fdisk.c +++ b/usr/src/cmd/fdisk/fdisk.c @@ -559,7 +559,7 @@ main(int argc, char *argv[]) * in that case leave the minfo structure zeroed */ if (ioctl(Dev, DKIOCGMEDIAINFO, &minfo)) { - memset(&minfo, 0, sizeof (minfo)); + (void) memset(&minfo, 0, sizeof (minfo)); } /* Get the disk geometry */ @@ -628,7 +628,12 @@ main(int argc, char *argv[]) Numcyl = disk_geom.dkg_ncyl; heads = disk_geom.dkg_nhead; sectors = disk_geom.dkg_nsect; - sectsiz = 512; + + if (minfo.dki_lbsize != 0) + sectsiz = minfo.dki_lbsize; + else + sectsiz = 512; + acyl = disk_geom.dkg_acyl; /* @@ -690,7 +695,11 @@ main(int argc, char *argv[]) Numcyl = disk_geom.dkg_ncyl; heads = disk_geom.dkg_nhead; sectors = disk_geom.dkg_nsect; - sectsiz = 512; + if (minfo.dki_lbsize != 0) + sectsiz = minfo.dki_lbsize; + else + sectsiz = 512; + acyl = disk_geom.dkg_acyl; (void) printf("* Label geometry for device %s\n", Dfltdev); (void) printf( @@ -751,7 +760,7 @@ main(int argc, char *argv[]) dev_capacity = minfo.dki_capacity; /* Allocate memory to hold three complete sectors */ - Bootsect = (char *)malloc(3 * sectsiz); + Bootsect = (char *)calloc(3 * sectsiz, 1); if (Bootsect == NULL) { (void) fprintf(stderr, "fdisk: Unable to obtain enough buffer memory" @@ -2819,8 +2828,8 @@ disptbl(void) (void) printf(HOME); (void) printf(T_LINE); (void) printf(" Total disk size is %d cylinders\n", Numcyl); - (void) printf(" Cylinder size is %d (512 byte) blocks\n\n", - heads * sectors); + (void) printf(" Cylinder size is %d (%d byte) blocks\n\n", + heads * sectors, sectsiz); (void) printf( " Cylinders\n"); (void) printf( @@ -3165,7 +3174,7 @@ getlong(char **bp) /* * copy_Table_to_Bootblk - * Copy the table into the 512 boot record. Note that the unused + * Copy the table into the boot record. Note that the unused * entries will always be the last ones in the table and they are * marked with 100 in sysind. The the unused portion of the table * is padded with zeros in the bytes after the used entries. @@ -3638,7 +3647,8 @@ clear_efi(void) */ dk_ioc.dki_lba = efi_vtoc->efi_last_u_lba + 1; dk_ioc.dki_length -= efi_vtoc->efi_lbasize; - dk_ioc.dki_data++; + dk_ioc.dki_data = (efi_gpt_t *)((char *)dk_ioc.dki_data + + efi_vtoc->efi_lbasize); if (io_debug) { (void) fprintf(stderr, "\tClearing backup partition table at block %lld\n", @@ -3656,7 +3666,8 @@ clear_efi(void) */ dk_ioc.dki_lba = efi_vtoc->efi_last_lba; dk_ioc.dki_length = efi_vtoc->efi_lbasize; - dk_ioc.dki_data--; + dk_ioc.dki_data = (efi_gpt_t *)((char *)dk_ioc.dki_data - + efi_vtoc->efi_lbasize); if (io_debug) { (void) fprintf(stderr, "\tClearing backup label at block " "%lld\n", dk_ioc.dki_lba); @@ -3685,14 +3696,14 @@ static void clear_vtoc(int table, int part) { struct ipart *clr_table; - struct dk_label disk_label; + char *disk_label; uint32_t pcyl, ncyl, count; diskaddr_t backup_block, solaris_offset; ssize_t bytes; off_t seek_byte; #ifdef DEBUG - struct dk_label read_label; + char *read_label; #endif /* DEBUG */ if (table == OLD) { @@ -3701,7 +3712,10 @@ clear_vtoc(int table, int part) clr_table = &Table[part]; } - (void) memset(&disk_label, 0, sizeof (struct dk_label)); + disk_label = (char *)calloc(sectsiz, 1); + if (disk_label == NULL) { + return; + } seek_byte = (off_t)(lel(clr_table->relsect) + VTOC_OFFSET) * sectsiz; @@ -3716,12 +3730,13 @@ clear_vtoc(int table, int part) (void) fprintf(stderr, "\tError seeking to primary label at byte %llu\n", (uint64_t)seek_byte); + free(disk_label); return; } - bytes = write(Dev, &disk_label, sizeof (struct dk_label)); + bytes = write(Dev, disk_label, sectsiz); - if (bytes != sizeof (struct dk_label)) { + if (bytes != sectsiz) { (void) fprintf(stderr, "\tWarning: only %d bytes written to clear primary" " VTOC!\n", bytes); @@ -3732,6 +3747,7 @@ clear_vtoc(int table, int part) (void) fprintf(stderr, "DEBUG: Error seeking to primary label at byte %llu\n", (uint64_t)seek_byte); + free(disk_label); return; } else { (void) fprintf(stderr, @@ -3739,15 +3755,21 @@ clear_vtoc(int table, int part) (uint64_t)seek_byte); } - bytes = read(Dev, &read_label, sizeof (struct dk_label)); + read_label = (char *)calloc(sectsiz, 1); + if (read_label == NULL) { + free(disk_label); + return; + } + + bytes = read(Dev, read_label, sectsiz); - if (bytes != sizeof (struct dk_label)) { + if (bytes != sectsiz) { (void) fprintf(stderr, "DEBUG: Warning: only %d bytes read of label\n", bytes); } - if (memcmp(&disk_label, &read_label, sizeof (struct dk_label)) != 0) { + if (memcmp(disk_label, read_label, sectsiz) != 0) { (void) fprintf(stderr, "DEBUG: Warning: disk_label and read_label differ!!!\n"); } else { @@ -3765,12 +3787,16 @@ clear_vtoc(int table, int part) (heads * sectors)) + ((heads - 1) * sectors) + 1; for (count = 1; count < 6; count++) { - seek_byte = (off_t)(solaris_offset + backup_block) * 512; + seek_byte = (off_t)(solaris_offset + backup_block) * sectsiz; if (lseek(Dev, seek_byte, SEEK_SET) == -1) { (void) fprintf(stderr, "\tError seeking to backup label at byte %llu on " "%s.\n", (uint64_t)seek_byte, Dfltdev); + free(disk_label); +#ifdef DEBUG + free(read_label); +#endif /* DEBUG */ return; } @@ -3781,9 +3807,9 @@ clear_vtoc(int table, int part) (uint64_t)(solaris_offset + backup_block)); } - bytes = write(Dev, &disk_label, sizeof (struct dk_label)); + bytes = write(Dev, disk_label, sectsiz); - if (bytes != sizeof (struct dk_label)) { + if (bytes != sectsiz) { (void) fprintf(stderr, "\t\tWarning: only %d bytes written to " "clear backup VTOC at block %llu!\n", bytes, @@ -3795,6 +3821,8 @@ clear_vtoc(int table, int part) (void) fprintf(stderr, "DEBUG: Error seeking to backup label at byte %llu\n", (uint64_t)seek_byte); + free(disk_label); + free(read_label); return; } else { (void) fprintf(stderr, @@ -3802,15 +3830,15 @@ clear_vtoc(int table, int part) (uint64_t)seek_byte); } - bytes = read(Dev, &read_label, sizeof (struct dk_label)); + bytes = read(Dev, read_label, sectsiz); - if (bytes != sizeof (struct dk_label)) { + if (bytes != sectsiz) { (void) fprintf(stderr, "DEBUG: Warning: only %d bytes read of backup label\n", bytes); } - if (memcmp(&disk_label, &read_label, sizeof (struct dk_label)) != 0) { + if (memcmp(disk_label, read_label, sectsiz) != 0) { (void) fprintf(stderr, "DEBUG: Warning: disk_label and read_label differ!!!\n"); } else { @@ -3818,10 +3846,16 @@ clear_vtoc(int table, int part) "DEBUG: Good compare of disk_label and backup " "read_label\n"); } + #endif /* DEBUG */ backup_block += 2; } + +#ifdef DEBUG + free(read_label); +#endif /* DEBUG */ + free(disk_label); } #define FDISK_STANDARD_LECTURE \ diff --git a/usr/src/cmd/fmthard/fmthard.c b/usr/src/cmd/fmthard/fmthard.c index 900bd8be6e..98faee8db3 100644 --- a/usr/src/cmd/fmthard/fmthard.c +++ b/usr/src/cmd/fmthard/fmthard.c @@ -29,7 +29,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -125,8 +125,8 @@ static char *uboot = ""; #endif /* various platform-specific definitions */ static char *ufirm = "firm"; -#if defined(_SUNOS_VTOC_16) static int sectsiz; +#if defined(_SUNOS_VTOC_16) static struct extvtoc disk_vtoc; #endif /* defined(_SUNOS_VTOC_16) */ @@ -143,6 +143,7 @@ main(int argc, char **argv) #endif /* defined(_SUNOS_VTOC_8) */ struct dk_gpt *disk_efi; struct dk_geom disk_geom; + struct dk_minfo minfo; int n; @@ -203,24 +204,32 @@ main(int argc, char **argv) if (stat(argv[optind], (struct stat *)&statbuf) == -1) { (void) fprintf(stderr, - "fmthard: Cannot stat device %s\n", - argv[optind]); + "fmthard: Cannot stat device %s\n", + argv[optind]); exit(1); } if ((statbuf.st_mode & S_IFMT) != S_IFCHR) { (void) fprintf(stderr, - "fmthard: %s must be a raw device.\n", - argv[optind]); + "fmthard: %s must be a raw device.\n", + argv[optind]); exit(1); } if ((fd = open(argv[optind], O_RDWR|O_NDELAY)) < 0) { (void) fprintf(stderr, "fmthard: Cannot open device %s - %s\n", - argv[optind], strerror(errno)); + argv[optind], strerror(errno)); exit(1); } + if (ioctl(fd, DKIOCGMEDIAINFO, &minfo) == 0) { + sectsiz = minfo.dki_lbsize; + } + + if (sectsiz == 0) { + sectsiz = SECSIZE; + } + /* * Get the geometry information for this disk from the driver */ @@ -233,7 +242,7 @@ main(int argc, char **argv) eflag++; } else { (void) fprintf(stderr, - "%s: Cannot get disk geometry\n", argv[optind]); + "%s: Cannot get disk geometry\n", argv[optind]); (void) close(fd); exit(1); } @@ -295,7 +304,7 @@ main(int argc, char **argv) FILE *fp; if ((fp = fopen(dfile, "r")) == NULL) { (void) fprintf(stderr, "Cannot open file %s\n", - dfile); + dfile); (void) close(fd); exit(1); } @@ -307,7 +316,6 @@ main(int argc, char **argv) } } - /* * Print the modified VTOC, rather than updating the disk */ @@ -326,10 +334,10 @@ main(int argc, char **argv) (void) memcpy(disk_vtoc.v_volume, vname, n); } else { for (c = 0; c < disk_efi->efi_nparts; c++) { - if (disk_efi->efi_parts[c].p_tag == + if (disk_efi->efi_parts[c].p_tag == V_RESERVED) { (void) memcpy(&disk_efi->efi_parts[c].p_name, - vname, n); + vname, n); } } } @@ -388,7 +396,7 @@ display(struct dk_geom *geom, struct extvtoc *vtoc, char *device) } (void) printf("*\n"); (void) printf("* Dimensions:\n"); - (void) printf("* %d bytes/sector\n", SECSIZE); + (void) printf("* %d bytes/sector\n", sectsiz); (void) printf("* %d sectors/track\n", geom->dkg_nsect); (void) printf("* %d tracks/cylinder\n", geom->dkg_nhead); (void) printf("* %d cylinders\n", geom->dkg_pcyl); @@ -404,10 +412,10 @@ display(struct dk_geom *geom, struct extvtoc *vtoc, char *device) if (vtoc->v_part[i].p_size > 0) (void) printf( " %d %d 0%x %llu %llu\n", - i, vtoc->v_part[i].p_tag, - vtoc->v_part[i].p_flag, - vtoc->v_part[i].p_start, - vtoc->v_part[i].p_size); + i, vtoc->v_part[i].p_tag, + vtoc->v_part[i].p_flag, + vtoc->v_part[i].p_start, + vtoc->v_part[i].p_size); } exit(0); } @@ -444,10 +452,10 @@ display64(struct dk_gpt *efi, char *device) if (efi->efi_parts[i].p_size > 0) (void) printf( " %d %d 0%x %8lld %8lld\n", - i, efi->efi_parts[i].p_tag, - efi->efi_parts[i].p_flag, - efi->efi_parts[i].p_start, - efi->efi_parts[i].p_size); + i, efi->efi_parts[i].p_tag, + efi->efi_parts[i].p_flag, + efi->efi_parts[i].p_start, + efi->efi_parts[i].p_size); } exit(0); } @@ -474,8 +482,8 @@ insert(char *data, struct extvtoc *vtoc) } if (part >= V_NUMPAR) { (void) fprintf(stderr, - "Error in data \"%s\": No such partition %x\n", - data, part); + "Error in data \"%s\": No such partition %x\n", + data, part); exit(1); } vtoc->v_part[part].p_tag = (ushort_t)tag; @@ -505,8 +513,8 @@ insert64(char *data, struct dk_gpt *efi) } if (part >= efi->efi_nparts) { (void) fprintf(stderr, - "Error in data \"%s\": No such partition %x\n", - data, part); + "Error in data \"%s\": No such partition %x\n", + data, part); exit(1); } efi->efi_parts[part].p_tag = (ushort_t)tag; @@ -558,19 +566,19 @@ load(FILE *fp, struct dk_geom *geom, struct extvtoc *vtoc) if (sscanf(line, "%d %d %x %llu %llu", &part, &tag, &flag, &start, &size) != 5) { (void) fprintf(stderr, "Syntax error: \"%s\"\n", - line); + line); exit(1); } if (part >= V_NUMPAR) { (void) fprintf(stderr, - "No such partition %x: \"%s\"\n", - part, line); + "No such partition %x: \"%s\"\n", + part, line); exit(1); } if (!eflag && ((start % nblks) != 0 || (size % nblks) != 0)) { (void) fprintf(stderr, "Partition %d not aligned on cylinder boundary: \"%s\"\n", - part, line); + part, line); exit(1); } vtoc->v_part[part].p_tag = (ushort_t)tag; @@ -609,7 +617,7 @@ load64(FILE *fp, int fd, struct dk_gpt **efi) if (sscanf(line, "%d %d %x %lld %lld", &part, &tag, &flag, &start, &size) != 5) { (void) fprintf(stderr, "Syntax error: \"%s\"\n", - line); + line); exit(1); } mem = realloc(mem, sizeof (*mem) * (nlines + 1)); @@ -624,13 +632,13 @@ load64(FILE *fp, int fd, struct dk_gpt **efi) } nlines++; if (part > max_part) - max_part = part; + max_part = part; } max_part++; if ((i = efi_alloc_and_init(fd, max_part, efi)) < 0) { (void) fprintf(stderr, - "efi_alloc_and_init failed: %d\n", i); + "efi_alloc_and_init failed: %d\n", i); exit(1); } for (i = 0; i < (*efi)->efi_nparts; ++i) { @@ -645,14 +653,14 @@ load64(FILE *fp, int fd, struct dk_gpt **efi) if (sscanf(mem[i], "%d %d %x %lld %lld", &part, &tag, &flag, &start, &size) != 5) { (void) fprintf(stderr, "Syntax error: \"%s\"\n", - line); + line); exit(1); } free(mem[i]); if (part >= (*efi)->efi_nparts) { (void) fprintf(stderr, - "No such partition %x: \"%s\"\n", - part, line); + "No such partition %x: \"%s\"\n", + part, line); exit(1); } (*efi)->efi_parts[part].p_tag = (ushort_t)tag; @@ -668,12 +676,13 @@ load64(FILE *fp, int fd, struct dk_gpt **efi) static void usage() { - (void) fprintf(stderr, #if defined(sparc) + (void) fprintf(stderr, "Usage: fmthard [ -i ] [ -n volumename ] [ -s datafile ] [ -d arguments] \ raw-device\n"); #elif defined(i386) + (void) fprintf(stderr, "Usage: fmthard [ -i ] [ -S ] [-I geom_file] \ -n volumename | -s datafile [ -d arguments] raw-device\n"); @@ -710,8 +719,6 @@ validate(struct dk_geom *geom, struct extvtoc *vtoc) vtoc->v_version = V_VERSION; vtoc->v_sanity = VTOC_SANE; vtoc->v_nparts = V_NUMPAR; - if (sectsiz == 0) - sectsiz = SECSIZE; if (vtoc->v_sectorsz == 0) vtoc->v_sectorsz = sectsiz; #endif /* defined(_SUNOS_VTOC_16) */ @@ -730,19 +737,19 @@ full size of disk. The full disk capacity is %llu sectors.\n", i, fullsz); if (vtoc->v_part[i].p_size == 0) continue; /* Undefined partition */ if ((vtoc->v_part[i].p_start % nblks) || - (vtoc->v_part[i].p_size % nblks)) { + (vtoc->v_part[i].p_size % nblks)) { (void) fprintf(stderr, "\ fmthard: Partition %d not aligned on cylinder boundary \n", i); exit(1); } if (vtoc->v_part[i].p_start > fullsz || - vtoc->v_part[i].p_start + - vtoc->v_part[i].p_size > fullsz) { + vtoc->v_part[i].p_start + + vtoc->v_part[i].p_size > fullsz) { (void) fprintf(stderr, "\ fmthard: Partition %d specified as %llu sectors starting at %llu\n\ \tdoes not fit. The full disk contains %llu sectors.\n", - i, vtoc->v_part[i].p_size, - vtoc->v_part[i].p_start, fullsz); + i, vtoc->v_part[i].p_size, + vtoc->v_part[i].p_start, fullsz); #if defined(sparc) exit(1); #endif @@ -763,7 +770,7 @@ fmthard: Partition %d specified as %llu sectors starting at %llu\n\ (isize != 0) && (jsize != 0)) { endsect = jstart + jsize -1; if ((jstart <= istart) && - (istart <= endsect)) { + (istart <= endsect)) { (void) fprintf(stderr, "\ fmthard: Partition %d overlaps partition %d. Overlap is allowed\n\ \tonly on partition on the full disk partition).\n", @@ -804,13 +811,13 @@ validate64(struct dk_gpt *efi) if (efi->efi_parts[i].p_tag == V_RESERVED) resv_part++; if (efi->efi_parts[i].p_start > fullsz || - efi->efi_parts[i].p_start + - efi->efi_parts[i].p_size > fullsz) { + efi->efi_parts[i].p_start + + efi->efi_parts[i].p_size > fullsz) { (void) fprintf(stderr, "\ fmthard: Partition %d specified as %lld sectors starting at %lld\n\ \tdoes not fit. The full disk contains %lld sectors.\n", - i, efi->efi_parts[i].p_size, - efi->efi_parts[i].p_start, fullsz); + i, efi->efi_parts[i].p_size, + efi->efi_parts[i].p_start, fullsz); exit(1); } @@ -827,7 +834,7 @@ fmthard: Partition %d specified as %lld sectors starting at %lld\n\ (isize != 0) && (jsize != 0)) { endsect = jstart + jsize - 1; if ((jstart <= istart) && - (istart <= endsect)) { + (istart <= endsect)) { (void) fprintf(stderr, "\ fmthard: Partition %d overlaps partition %d. Overlap is allowed\n\ \tonly on partition on the full disk partition).\n", @@ -863,10 +870,10 @@ vread(int fd, struct extvtoc *vtoc, char *devname) } if (i == VT_EINVAL) { (void) fprintf(stderr, "%s: Invalid VTOC\n", - devname); + devname); } else { (void) fprintf(stderr, "%s: Cannot read VTOC\n", - devname); + devname); } exit(1); } @@ -881,12 +888,12 @@ vread64(int fd, struct dk_gpt **efi_hdr, char *devname) if ((i = efi_alloc_and_read(fd, efi_hdr)) < 0) { if (i == VT_EINVAL) (void) fprintf(stderr, - "%s: this disk must be labeled first\n", - devname); + "%s: this disk must be labeled first\n", + devname); else (void) fprintf(stderr, - "%s: read_efi failed %d\n", - devname, i); + "%s: read_efi failed %d\n", + devname, i); exit(1); } lastlba = (*efi_hdr)->efi_last_u_lba; @@ -904,10 +911,10 @@ vwrite(int fd, struct extvtoc *vtoc, char *devname) if (i == VT_EINVAL) { (void) fprintf(stderr, "%s: invalid entry exists in vtoc\n", - devname); + devname); } else { (void) fprintf(stderr, "%s: Cannot write VTOC\n", - devname); + devname); } exit(1); } @@ -925,10 +932,10 @@ vwrite64(int fd, struct dk_gpt *efi, char *devname) if (i == VT_EINVAL) { (void) fprintf(stderr, "%s: invalid entry exists in vtoc\n", - devname); + devname); } else { (void) fprintf(stderr, "%s: Cannot write EFI\n", - devname); + devname); } exit(1); } diff --git a/usr/src/cmd/format/analyze.c b/usr/src/cmd/format/analyze.c index 8d8404b280..64417130d2 100644 --- a/usr/src/cmd/format/analyze.c +++ b/usr/src/cmd/format/analyze.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -461,7 +461,7 @@ scan_repair(bn, mode) { int status; int result = 1; - char buf[SECSIZE]; + char *buf; int buf_is_good; int i; @@ -471,6 +471,11 @@ scan_repair(bn, mode) return (result); } + buf = malloc(cur_blksz); + if (buf == NULL) { + err_print("Warning: no memory.\n\n"); + return (result); + } enter_critical(); /* @@ -509,7 +514,7 @@ scan_repair(bn, mode) * determine if the new block appears ok. */ if (!buf_is_good) { - bzero(buf, SECSIZE); + bzero(buf, cur_blksz); fmt_print("Warning: Block %llu zero-filled.\n", bn); } else { fmt_print("ok.\n"); @@ -565,7 +570,7 @@ scan_repair(bn, mode) } exit_critical(); - + free(buf); return (result); } @@ -596,7 +601,7 @@ analyze_blocks(flags, blkno, blkcnt, data, init, driver_flags, xfercntp) /* * Initialize the pattern buffer if necessary. */ - nints = (diskaddr_t)blkcnt * SECSIZE / sizeof (int); + nints = (diskaddr_t)blkcnt * cur_blksz / sizeof (int); if ((flags & SCAN_PATTERN) && init) { for (i = 0; i < nints; i++) *((int *)((int *)pattern_buf + i)) = data; @@ -724,7 +729,7 @@ verify_blocks(int flags, int status, i, nints; unsigned *ptr = (uint_t *)pattern_buf; - nints = SECSIZE / sizeof (int); + nints = cur_blksz / sizeof (int); /* * Initialize the pattern buffer if we are in write pass. diff --git a/usr/src/cmd/format/auto_sense.c b/usr/src/cmd/format/auto_sense.c index 094c6c2c1d..57d44562a6 100644 --- a/usr/src/cmd/format/auto_sense.c +++ b/usr/src/cmd/format/auto_sense.c @@ -223,8 +223,6 @@ static char *get_sun_disk_name( static char *get_generic_disk_name( char *disk_name, struct scsi_inquiry *inquiry); -static int force_blocksize(int fd); -static int raw_format(int fd); static char *strcopy( char *dst, char *src, @@ -308,10 +306,10 @@ auto_efi_sense(int fd, struct efi_info *label) */ if (ioctl(fd, DKIOCINFO, &dkinfo) == -1) { - if (option_msg && diag_msg) { - err_print("DKIOCINFO failed\n"); - } - return (NULL); + if (option_msg && diag_msg) { + err_print("DKIOCINFO failed\n"); + } + return (NULL); } if ((cur_ctype != NULL) && (cur_ctype->ctype_ctype == DKC_DIRECT)) { ctlr = find_direct_ctlr_info(&dkinfo); @@ -337,11 +335,11 @@ auto_efi_sense(int fd, struct efi_info *label) disk->dtype_next = NULL; (void) strlcpy(disk->vendor, label->vendor, - sizeof (disk->vendor)); + sizeof (disk->vendor)); (void) strlcpy(disk->product, label->product, - sizeof (disk->product)); + sizeof (disk->product)); (void) strlcpy(disk->revision, label->revision, - sizeof (disk->revision)); + sizeof (disk->revision)); disk->capacity = label->capacity; part = (struct partition_info *) @@ -554,11 +552,6 @@ auto_label_init(struct dk_label *label) disk_info.dki_lbsize = DEV_BSIZE; } - if (disk_info.dki_lbsize != DEV_BSIZE) { - err_print("auto_label_init: lbasize is not 512\n"); - goto auto_label_init_out; - } - dk_ioc_back.dki_data = databack; /* @@ -584,7 +577,7 @@ auto_label_init(struct dk_label *label) goto auto_label_init_out; } - backsigp = (efi_gpt_t *)((uintptr_t)dk_ioc_back.dki_data + DEV_BSIZE); + backsigp = (efi_gpt_t *)((uintptr_t)dk_ioc_back.dki_data + cur_blksz); backsig = backsigp->efi_gpt_Signature; @@ -736,7 +729,7 @@ new_direct_disk_type( disk->dtype_rpm = label->dkl_rpm; part = (struct partition_info *) - zalloc(sizeof (struct partition_info)); + zalloc(sizeof (struct partition_info)); pt = disk->dtype_plist; if (pt == NULL) { disk->dtype_plist = part; @@ -764,11 +757,11 @@ new_direct_disk_type( #elif defined(_SUNOS_VTOC_16) part->pinfo_map[i].dkl_cylno = - label->dkl_vtoc.v_part[i].p_start / - ((blkaddr_t)(disk->dtype_nhead * - disk->dtype_nsect - apc)); + label->dkl_vtoc.v_part[i].p_start / + ((blkaddr_t)(disk->dtype_nhead * + disk->dtype_nsect - apc)); part->pinfo_map[i].dkl_nblk = - label->dkl_vtoc.v_part[i].p_size; + label->dkl_vtoc.v_part[i].p_size; #else #error No VTOC format defined. #endif /* defined(_SUNOS_VTOC_8) */ @@ -779,7 +772,7 @@ new_direct_disk_type( */ if (label->dkl_vtoc.v_version == V_VERSION) { (void) memcpy(disk_info->v_volume, label->dkl_vtoc.v_volume, - LEN_DKL_VVOL); + LEN_DKL_VVOL); part->vtoc = label->dkl_vtoc; } else { (void) memset(disk_info->v_volume, 0, LEN_DKL_VVOL); @@ -845,10 +838,10 @@ auto_sense( deflt = 1; ioparam.io_charlist = confirm_list; if (input(FIO_MSTR, FORMAT_MSG, '?', &ioparam, - &deflt, DATA_INPUT) == 0) { + &deflt, DATA_INPUT) == 0) { force_format_dat = 1; } else if (input(FIO_MSTR, GENERIC_MSG, '?', &ioparam, - &deflt, DATA_INPUT) == 0) { + &deflt, DATA_INPUT) == 0) { force_generic = 1; } } @@ -890,7 +883,7 @@ auto_sense( } if (option_msg && diag_msg) { err_print("blocks: %llu (0x%llx)\n", - capacity.sc_capacity, capacity.sc_capacity); + capacity.sc_capacity, capacity.sc_capacity); err_print("blksize: %u\n", capacity.sc_lbasize); } @@ -910,7 +903,7 @@ auto_sense( if (force_generic) { return (generic_disk_sense(fd, can_prompt, label, - &inquiry, &capacity, disk_name)); + &inquiry, &capacity, disk_name)); } /* @@ -918,7 +911,7 @@ auto_sense( */ if ((disk_type = find_scsi_disk_by_name(disk_name)) != NULL) { if (use_existing_disk_type(fd, can_prompt, label, - &inquiry, disk_type, &capacity)) { + &inquiry, disk_type, &capacity)) { return (disk_type); } if (force_format_dat) { @@ -931,7 +924,7 @@ auto_sense( */ return (generic_disk_sense(fd, can_prompt, label, - &inquiry, &capacity, disk_name)); + &inquiry, &capacity, disk_name)); } @@ -964,7 +957,6 @@ generic_disk_sense( struct mode_geometry page4; uchar_t buf4[MAX_MODE_SENSE_SIZE]; } u_page4; - struct scsi_capacity_16 new_capacity; struct mode_format *page3 = &u_page3.page3; struct mode_geometry *page4 = &u_page4.page4; struct scsi_ms_header header; @@ -982,38 +974,6 @@ generic_disk_sense( } /* - * If the device's block size is not 512, we have to - * change block size, reformat, and then sense the - * geometry. To do this, we must be able to prompt - * the user. - */ - if (capacity->sc_lbasize != DEV_BSIZE) { - if (!can_prompt) { - return (NULL); - } - if (force_blocksize(fd)) { - goto err; - } - - /* - * Get the capacity again, since this has changed - */ - if (uscsi_read_capacity(fd, &new_capacity)) { - goto err; - } - if (option_msg && diag_msg) { - err_print("blocks: %llu (0x%llx)\n", - new_capacity.sc_capacity, - new_capacity.sc_capacity); - err_print("blksize: %u\n", new_capacity.sc_lbasize); - } - capacity = &new_capacity; - if (capacity->sc_lbasize != DEV_BSIZE) { - goto err; - } - } - - /* * Get the number of blocks from Read Capacity data. Note that * the logical block address range from 0 to capacity->sc_capacity. * Limit the size to 2 TB (UINT32_MAX) to use with SMI labels. @@ -1028,7 +988,7 @@ generic_disk_sense( * Get current Page 3 - Format Parameters page */ if (uscsi_mode_sense(fd, DAD_MODE_FORMAT, MODE_SENSE_PC_CURRENT, - (caddr_t)&u_page3, MAX_MODE_SENSE_SIZE, &header)) { + (caddr_t)&u_page3, MAX_MODE_SENSE_SIZE, &header)) { setdefault = 1; } @@ -1036,7 +996,7 @@ generic_disk_sense( * Get current Page 4 - Drive Geometry page */ if (uscsi_mode_sense(fd, DAD_MODE_GEOMETRY, MODE_SENSE_PC_CURRENT, - (caddr_t)&u_page4, MAX_MODE_SENSE_SIZE, &header)) { + (caddr_t)&u_page4, MAX_MODE_SENSE_SIZE, &header)) { setdefault = 1; } @@ -1071,7 +1031,7 @@ generic_disk_sense( &nsect); } else { pcyl = (page4->cyl_ub << 16) + (page4->cyl_mb << 8) + - page4->cyl_lb; + page4->cyl_lb; nhead = page4->heads; nsect = page3->sect_track; } @@ -1094,7 +1054,12 @@ generic_disk_sense( } } - if (setdefault == 1) { + /* + * Mode sense page 3 and page 4 are obsolete in SCSI-3. For + * newly developed large sector size disk, we will not rely on + * those two pages but compute geometry directly. + */ + if ((setdefault == 1) || (capacity->sc_lbasize != DEV_BSIZE)) { /* * If the number of cylinders or the number of heads reported * is zero, we think the inquiry of page 3 and page 4 failed. @@ -1223,7 +1188,7 @@ generic_disk_sense( p, nhead, n); if (input(FIO_INT, "Select one of the above " "choices ", ':', &ioparam, - &deflt, DATA_INPUT) == 2) { + &deflt, DATA_INPUT) == 2) { pcyl = p; nsect = n; } @@ -1239,16 +1204,16 @@ generic_disk_sense( */ if ((pcyl > MAXIMUM_NO_CYLINDERS && - ((nsect > MAXIMUM_NO_SECTORS) || - (nhead > MAXIMUM_NO_HEADS))) || - ((nsect > MAXIMUM_NO_SECTORS) && - (nhead > MAXIMUM_NO_HEADS))) { + ((nsect > MAXIMUM_NO_SECTORS) || + (nhead > MAXIMUM_NO_HEADS))) || + ((nsect > MAXIMUM_NO_SECTORS) && + (nhead > MAXIMUM_NO_HEADS))) { err_print("This disk is too big to label. " - " You will lose some blocks.\n"); + " You will lose some blocks.\n"); } if ((pcyl > MAXIMUM_NO_CYLINDERS) || - (nsect > MAXIMUM_NO_SECTORS) || - (nhead > MAXIMUM_NO_HEADS)) { + (nsect > MAXIMUM_NO_SECTORS) || + (nhead > MAXIMUM_NO_HEADS)) { u_ioparam_t ioparam; int order; char msg[256]; @@ -1259,45 +1224,45 @@ generic_disk_sense( switch (order) { case 0x7: /* pcyl > nhead > nsect */ nblocks = - square_box(nblocks, - &pcyl, MAXIMUM_NO_CYLINDERS, - &nhead, MAXIMUM_NO_HEADS, - &nsect, MAXIMUM_NO_SECTORS); + square_box(nblocks, + &pcyl, MAXIMUM_NO_CYLINDERS, + &nhead, MAXIMUM_NO_HEADS, + &nsect, MAXIMUM_NO_SECTORS); break; case 0x6: /* pcyl > nsect > nhead */ nblocks = - square_box(nblocks, - &pcyl, MAXIMUM_NO_CYLINDERS, - &nsect, MAXIMUM_NO_SECTORS, - &nhead, MAXIMUM_NO_HEADS); + square_box(nblocks, + &pcyl, MAXIMUM_NO_CYLINDERS, + &nsect, MAXIMUM_NO_SECTORS, + &nhead, MAXIMUM_NO_HEADS); break; case 0x4: /* nsect > pcyl > nhead */ nblocks = - square_box(nblocks, - &nsect, MAXIMUM_NO_SECTORS, - &pcyl, MAXIMUM_NO_CYLINDERS, - &nhead, MAXIMUM_NO_HEADS); + square_box(nblocks, + &nsect, MAXIMUM_NO_SECTORS, + &pcyl, MAXIMUM_NO_CYLINDERS, + &nhead, MAXIMUM_NO_HEADS); break; case 0x0: /* nsect > nhead > pcyl */ nblocks = - square_box(nblocks, - &nsect, MAXIMUM_NO_SECTORS, - &nhead, MAXIMUM_NO_HEADS, - &pcyl, MAXIMUM_NO_CYLINDERS); + square_box(nblocks, + &nsect, MAXIMUM_NO_SECTORS, + &nhead, MAXIMUM_NO_HEADS, + &pcyl, MAXIMUM_NO_CYLINDERS); break; case 0x3: /* nhead > pcyl > nsect */ nblocks = - square_box(nblocks, - &nhead, MAXIMUM_NO_HEADS, - &pcyl, MAXIMUM_NO_CYLINDERS, - &nsect, MAXIMUM_NO_SECTORS); + square_box(nblocks, + &nhead, MAXIMUM_NO_HEADS, + &pcyl, MAXIMUM_NO_CYLINDERS, + &nsect, MAXIMUM_NO_SECTORS); break; case 0x1: /* nhead > nsect > pcyl */ nblocks = - square_box(nblocks, - &nhead, MAXIMUM_NO_HEADS, - &nsect, MAXIMUM_NO_SECTORS, - &pcyl, MAXIMUM_NO_CYLINDERS); + square_box(nblocks, + &nhead, MAXIMUM_NO_HEADS, + &nsect, MAXIMUM_NO_SECTORS, + &pcyl, MAXIMUM_NO_CYLINDERS); break; default: /* How did we get here? */ @@ -1305,10 +1270,10 @@ generic_disk_sense( /* Do something useful */ nblocks = - square_box(nblocks, - &nhead, MAXIMUM_NO_HEADS, - &nsect, MAXIMUM_NO_SECTORS, - &pcyl, MAXIMUM_NO_CYLINDERS); + square_box(nblocks, + &nhead, MAXIMUM_NO_HEADS, + &nsect, MAXIMUM_NO_SECTORS, + &pcyl, MAXIMUM_NO_CYLINDERS); break; } if (option_msg && diag_msg && @@ -1333,7 +1298,7 @@ generic_disk_sense( ioparam.io_charlist = confirm_list; if (input(FIO_MSTR, msg, '?', &ioparam, - &deflt, DATA_INPUT) != 0) + &deflt, DATA_INPUT) != 0) break; ioparam.io_bounds.lower = MINIMUM_NO_HEADS; @@ -1417,7 +1382,7 @@ generic_disk_sense( char old_name[DISK_NAME_MAX]; (void) strcpy(old_name, disk_name); (void) get_generic_disk_name(disk_name, - inquiry); + inquiry); if (option_msg && diag_msg) { err_print( "Changing disk type name from '%s' to '%s'\n", old_name, disk_name); @@ -1457,7 +1422,6 @@ use_existing_disk_type( struct disk_type *disk_type, struct scsi_capacity_16 *capacity) { - struct scsi_capacity_16 new_capacity; int pcyl; int acyl; int nhead; @@ -1465,40 +1429,6 @@ use_existing_disk_type( int rpm; /* - * If the device's block size is not 512, we have to - * change block size, reformat, and then sense the - * geometry. To do this, we must be able to prompt - * the user. - */ - if (capacity->sc_lbasize != DEV_BSIZE) { - if (!can_prompt) { - return (0); - } - if (force_blocksize(fd)) { - goto err; - } - - /* - * Get the capacity again, since this has changed - */ - if (uscsi_read_capacity(fd, &new_capacity)) { - goto err; - } - - if (option_msg && diag_msg) { - err_print("blocks: %llu (0x%llx)\n", - new_capacity.sc_capacity, - new_capacity.sc_capacity); - err_print("blksize: %u\n", new_capacity.sc_lbasize); - } - - capacity = &new_capacity; - if (capacity->sc_lbasize != DEV_BSIZE) { - goto err; - } - } - - /* * Construct a new label out of the format.dat */ pcyl = disk_type->dtype_pcyl; @@ -1545,7 +1475,7 @@ use_existing_disk_type( err: if (option_msg && diag_msg) { err_print( - "Configuration via format.dat geometry failed\n"); + "Configuration via format.dat geometry failed\n"); } return (0); } @@ -1589,11 +1519,11 @@ build_default_partition( * is in integral number of megabytes. */ capacity = ((diskaddr_t)(label->dkl_ncyl) * label->dkl_nhead * - label->dkl_nsect) / (1024 * 1024) / DEV_BSIZE; + label->dkl_nsect) / (1024 * 1024) / cur_blksz; dpt = default_partitions; for (i = 0; i < DEFAULT_PARTITION_TABLE_SIZE; i++, dpt++) { if (capacity >= dpt->min_capacity && - capacity < dpt->max_capacity) { + capacity < dpt->max_capacity) { break; } } @@ -1623,7 +1553,7 @@ build_default_partition( * cylinders. Always give what they * asked or more, never less. */ - nblks = pt->partitions[i] * ((1024*1024)/DEV_BSIZE); + nblks = pt->partitions[i] * ((1024*1024)/cur_blksz); nblks += (blks_per_cyl - 1); ncyls[i] = nblks / blks_per_cyl; freecyls -= ncyls[i]; @@ -1639,7 +1569,7 @@ build_default_partition( i, ncyls[i]); } err_print("Free cylinders exhausted (%d)\n", - freecyls); + freecyls); } return (0); } @@ -1733,13 +1663,13 @@ build_default_partition( #if defined(_SUNOS_VTOC_8) label->dkl_map[2].dkl_cylno = 0; label->dkl_map[2].dkl_nblk = - label->dkl_ncyl * label->dkl_nhead * label->dkl_nsect; + label->dkl_ncyl * label->dkl_nhead * label->dkl_nsect; #elif defined(_SUNOS_VTOC_16) label->dkl_vtoc.v_part[2].p_start = 0; label->dkl_vtoc.v_part[2].p_size = - (label->dkl_ncyl + label->dkl_acyl) * label->dkl_nhead * - label->dkl_nsect; + (label->dkl_ncyl + label->dkl_acyl) * label->dkl_nhead * + label->dkl_nsect; #else #error No VTOC format defined. #endif /* defined(_SUNOS_VTOC_8) */ @@ -1776,13 +1706,12 @@ build_default_partition( } else { err_print("%6.2fMB ", scaled); } - err_print(" %6d cylinders\n", #if defined(_SUNOS_VTOC_8) + err_print(" %6d cylinders\n", label->dkl_map[i].dkl_nblk/blks_per_cyl); - #elif defined(_SUNOS_VTOC_16) + err_print(" %6d cylinders\n", label->dkl_vtoc.v_part[i].p_size/blks_per_cyl); - #else #error No VTOC format defined. #endif /* defined(_SUNOS_VTOC_8) */ @@ -1810,16 +1739,16 @@ find_scsi_disk_type( ctlr = find_scsi_ctlr_type(); for (dp = ctlr->ctype_dlist; dp != NULL; dp = dp->dtype_next) { - if (dp->dtype_asciilabel) { - if ((strcmp(dp->dtype_asciilabel, disk_name) == 0) && - dp->dtype_pcyl == label->dkl_pcyl && - dp->dtype_ncyl == label->dkl_ncyl && - dp->dtype_acyl == label->dkl_acyl && - dp->dtype_nhead == label->dkl_nhead && - dp->dtype_nsect == label->dkl_nsect) { - return (dp); + if (dp->dtype_asciilabel) { + if ((strcmp(dp->dtype_asciilabel, disk_name) == 0) && + dp->dtype_pcyl == label->dkl_pcyl && + dp->dtype_ncyl == label->dkl_ncyl && + dp->dtype_acyl == label->dkl_acyl && + dp->dtype_nhead == label->dkl_nhead && + dp->dtype_nsect == label->dkl_nsect) { + return (dp); + } } - } } return ((struct disk_type *)NULL); @@ -1839,11 +1768,11 @@ find_scsi_disk_by_name( ctlr = find_scsi_ctlr_type(); for (dp = ctlr->ctype_dlist; dp != NULL; dp = dp->dtype_next) { - if (dp->dtype_asciilabel) { - if ((strcmp(dp->dtype_asciilabel, disk_name) == 0)) { - return (dp); + if (dp->dtype_asciilabel) { + if ((strcmp(dp->dtype_asciilabel, disk_name) == 0)) { + return (dp); + } } - } } return ((struct disk_type *)NULL); @@ -1997,7 +1926,7 @@ new_scsi_disk_type( */ if (part == NULL) { part = (struct partition_info *) - zalloc(sizeof (struct partition_info)); + zalloc(sizeof (struct partition_info)); pt = disk->dtype_plist; if (pt == NULL) { disk->dtype_plist = part; @@ -2024,11 +1953,11 @@ new_scsi_disk_type( #elif defined(_SUNOS_VTOC_16) part->pinfo_map[i].dkl_cylno = - label->dkl_vtoc.v_part[i].p_start / - ((blkaddr32_t)(disk->dtype_nhead * - disk->dtype_nsect - apc)); + label->dkl_vtoc.v_part[i].p_start / + ((blkaddr32_t)(disk->dtype_nhead * + disk->dtype_nsect - apc)); part->pinfo_map[i].dkl_nblk = - label->dkl_vtoc.v_part[i].p_size; + label->dkl_vtoc.v_part[i].p_size; #else #error No VTOC format defined. #endif /* defined(_SUNOS_VTOC_8) */ @@ -2042,7 +1971,7 @@ new_scsi_disk_type( */ if (label->dkl_vtoc.v_version == V_VERSION) { (void) memcpy(disk_info->v_volume, label->dkl_vtoc.v_volume, - LEN_DKL_VVOL); + LEN_DKL_VVOL); part->vtoc = label->dkl_vtoc; } else { (void) memset(disk_info->v_volume, 0, LEN_DKL_VVOL); @@ -2151,112 +2080,16 @@ get_generic_disk_name( (void) memset(disk_name, 0, DISK_NAME_MAX); p = strcopy(disk_name, inquiry->inq_vid, - sizeof (inquiry->inq_vid)); + sizeof (inquiry->inq_vid)); *p++ = '-'; p = strcopy(p, inquiry->inq_pid, sizeof (inquiry->inq_pid)); *p++ = '-'; p = strcopy(p, inquiry->inq_revision, - sizeof (inquiry->inq_revision)); + sizeof (inquiry->inq_revision)); return (disk_name); } - - -static int -force_blocksize( - int fd) -{ - union { - struct mode_format page3; - uchar_t buf3[MAX_MODE_SENSE_SIZE]; - } u_page3; - struct mode_format *page3 = &u_page3.page3; - struct scsi_ms_header header; - - if (check("\ -Must reformat device to 512-byte blocksize. Continue") == 0) { - - /* - * Get current Page 3 - Format Parameters page - */ - if (uscsi_mode_sense(fd, DAD_MODE_FORMAT, - MODE_SENSE_PC_CURRENT, (caddr_t)&u_page3, - MAX_MODE_SENSE_SIZE, &header)) { - goto err; - } - - /* - * Make our changes to the geometry - */ - header.mode_header.length = 0; - header.mode_header.device_specific = 0; - page3->mode_page.ps = 0; - page3->data_bytes_sect = DEV_BSIZE; - - /* - * make sure that logical block size is of - * DEV_BSIZE. - */ - header.block_descriptor.blksize_hi = (DEV_BSIZE >> 16); - header.block_descriptor.blksize_mid = (DEV_BSIZE >> 8); - header.block_descriptor.blksize_lo = (char)(DEV_BSIZE); - /* - * Select current Page 3 - Format Parameters page - */ - if (uscsi_mode_select(fd, DAD_MODE_FORMAT, - MODE_SELECT_PF, (caddr_t)&u_page3, - MODESENSE_PAGE_LEN(&u_page3), &header)) { - goto err; - } - - /* - * Now reformat the device - */ - if (raw_format(fd)) { - goto err; - } - return (0); - } - -err: - if (option_msg && diag_msg) { - err_print( - "Reformat device to 512-byte blocksize failed\n"); - } - return (1); -} - -static int -raw_format( - int fd) -{ - union scsi_cdb cdb; - struct uscsi_cmd ucmd; - struct scsi_defect_hdr defect_hdr; - - (void) memset((char *)&ucmd, 0, sizeof (ucmd)); - (void) memset((char *)&cdb, 0, sizeof (union scsi_cdb)); - (void) memset((char *)&defect_hdr, 0, sizeof (defect_hdr)); - cdb.scc_cmd = SCMD_FORMAT; - ucmd.uscsi_cdb = (caddr_t)&cdb; - ucmd.uscsi_cdblen = CDB_GROUP0; - ucmd.uscsi_bufaddr = (caddr_t)&defect_hdr; - ucmd.uscsi_buflen = sizeof (defect_hdr); - cdb.cdb_opaque[1] = FPB_DATA; - - /* - * Issue the format ioctl - */ - fmt_print("Formatting...\n"); - (void) fflush(stdout); - if (uscsi_cmd(fd, &ucmd, - (option_msg && diag_msg) ? F_NORMAL : F_SILENT)) { - return (1); - } - return (0); -} - /* * Copy a string of characters from src to dst, for at * most n bytes. Strip all leading and trailing spaces, @@ -2383,7 +2216,8 @@ square_box( * any blocks. */ - for (i = 0; (((*dim1)>>i)&1) == 0 && ((*dim1)>>i) > lim1; i++); + for (i = 0; (((*dim1)>>i)&1) == 0 && ((*dim1)>>i) > lim1; i++) + ; if (i) { *dim1 = ((*dim1)>>i); *dim3 = ((*dim3)<<i); diff --git a/usr/src/cmd/format/ctlr_ata.c b/usr/src/cmd/format/ctlr_ata.c index 2f417b9b78..c8f982d71b 100644 --- a/usr/src/cmd/format/ctlr_ata.c +++ b/usr/src/cmd/format/ctlr_ata.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -155,7 +155,7 @@ ata_rdwr(int dir, int fd, diskaddr_t blk64, int secnt, caddr_t bufaddr, blkno = (blkaddr_t)blk64; bzero((caddr_t)&dadkio_rwcmd, sizeof (struct dadkio_rwcmd)); - tmpsec = secnt * 512; + tmpsec = secnt * cur_blksz; /* Doing raw read */ dadkio_rwcmd.cmd = (dir == DIR_READ) ? DADKIO_RWCMD_READ : @@ -213,12 +213,15 @@ ata_rdwr(int dir, int fd, diskaddr_t blk64, int secnt, caddr_t bufaddr, int ata_ck_format() { - unsigned char bufaddr[2048]; + char *bufaddr; int status; + bufaddr = (char *)zalloc(4 * cur_blksz); status = ata_rdwr(DIR_READ, cur_file, (diskaddr_t)1, 4, (caddr_t)bufaddr, 0, NULL); + free(bufaddr); + return (!status); } diff --git a/usr/src/cmd/format/ctlr_scsi.c b/usr/src/cmd/format/ctlr_scsi.c index c9ddee8f15..c16327832d 100644 --- a/usr/src/cmd/format/ctlr_scsi.c +++ b/usr/src/cmd/format/ctlr_scsi.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -264,7 +264,7 @@ scsi_rdwr(dir, fd, blkno, secnt, bufaddr, flags, xfercntp) } ucmd.uscsi_cdb = (caddr_t)&cdb; ucmd.uscsi_bufaddr = bufaddr; - ucmd.uscsi_buflen = nsectors * SECSIZE; + ucmd.uscsi_buflen = nsectors * cur_blksz; rc = uscsi_cmd(fd, &ucmd, flags); if (rc != 0) @@ -290,7 +290,7 @@ scsi_rdwr(dir, fd, blkno, secnt, bufaddr, flags, xfercntp) blkno += nsectors; secnt -= nsectors; - bufaddr += nsectors * SECSIZE; + bufaddr += nsectors * cur_blksz; } /* @@ -326,7 +326,7 @@ scsi_ck_format(void) * Try to read the first four blocks. */ status = scsi_rdwr(DIR_READ, cur_file, (diskaddr_t)0, 4, - (caddr_t)cur_buf, F_SILENT, NULL); + (caddr_t)cur_buf, F_SILENT, NULL); return (!status); } @@ -498,7 +498,7 @@ scsi_raw_format(void) "by format verification and surface analysis.\n\n"); if (check("Retry format without mode selects and Grown Defects list") - != 0) { + != 0) { return (-1); } @@ -580,18 +580,18 @@ scsi_format_time() * If it fail, try to use the saved or current instead. */ status = uscsi_mode_sense(cur_file, DAD_MODE_GEOMETRY, - MODE_SENSE_PC_DEFAULT, (caddr_t)page4, - MAX_MODE_SENSE_SIZE, &header); + MODE_SENSE_PC_DEFAULT, (caddr_t)page4, + MAX_MODE_SENSE_SIZE, &header); if (status) { status = uscsi_mode_sense(cur_file, DAD_MODE_GEOMETRY, - MODE_SENSE_PC_SAVED, (caddr_t)page4, - MAX_MODE_SENSE_SIZE, &header); + MODE_SENSE_PC_SAVED, (caddr_t)page4, + MAX_MODE_SENSE_SIZE, &header); } if (status) { status = uscsi_mode_sense(cur_file, DAD_MODE_GEOMETRY, - MODE_SENSE_PC_CURRENT, (caddr_t)page4, - MAX_MODE_SENSE_SIZE, &header); + MODE_SENSE_PC_CURRENT, (caddr_t)page4, + MAX_MODE_SENSE_SIZE, &header); } if (status) { return (0); @@ -609,7 +609,7 @@ scsi_format_time() page4->rpm = BE_16(page4->rpm); p4_cylinders = (page4->cyl_ub << 16) + (page4->cyl_mb << 8) + - page4->cyl_lb; + page4->cyl_lb; p4_heads = page4->heads; p4_rpm = page4->rpm; @@ -618,7 +618,7 @@ scsi_format_time() */ if (p4_rpm < MIN_RPM || p4_rpm > MAX_RPM) { err_print("Mode sense page(4) reports rpm value as %d," - " adjusting it to %d\n", p4_rpm, AVG_RPM); + " adjusting it to %d\n", p4_rpm, AVG_RPM); p4_rpm = AVG_RPM; } @@ -626,7 +626,7 @@ scsi_format_time() return (0); format_time = ((scsi_format_revolutions * p4_heads * - p4_cylinders) + p4_rpm) / p4_rpm; + p4_cylinders) + p4_rpm) / p4_rpm; if (option_msg && diag_msg) { err_print(" pcyl: %d\n", p4_cylinders); @@ -1027,8 +1027,8 @@ scsi_ms_page3(scsi2_flag) tmp5 = page3->alt_tracks_vol; tmp6 = page3->alt_sect_zone; - flag = (page3->data_bytes_sect != SECSIZE); - page3->data_bytes_sect = SECSIZE; + flag = (page3->data_bytes_sect != cur_blksz); + page3->data_bytes_sect = cur_blksz; flag |= (page3->interleave != 1); page3->interleave = 1; @@ -1844,7 +1844,8 @@ scsi_convert_list_to_new(list, def_list, list_format) len = def_list->length / sizeof (struct scsi_bfi_defect); old_defect = def_list->list; new_defect = (struct defect_entry *) - zalloc(LISTSIZE(len) * SECSIZE); + zalloc(deflist_size(cur_blksz, len) * + cur_blksz); list->header.magicno = (uint_t)DEFECT_MAGIC; list->list = new_defect; @@ -2618,7 +2619,7 @@ uscsi_reserve_release(int fd, int cmd) ucmd.uscsi_cdb = (caddr_t)&cdb; ucmd.uscsi_cdblen = CDB_GROUP0; status = uscsi_cmd(fd, &ucmd, - (option_msg && diag_msg) ? F_NORMAL : F_SILENT); + (option_msg && diag_msg) ? F_NORMAL : F_SILENT); if (status) { /* @@ -2630,14 +2631,14 @@ uscsi_reserve_release(int fd, int cmd) (void) memset((char *)&cdb, 0, sizeof (union scsi_cdb)); ucmd.uscsi_cdb = (caddr_t)&cdb; cdb.scc_cmd = (cmd == SCMD_RESERVE) ? - SCMD_RESERVE_G1 : SCMD_RELEASE_G1; + SCMD_RESERVE_G1 : SCMD_RELEASE_G1; ucmd.uscsi_cdblen = CDB_GROUP1; status = uscsi_cmd(fd, &ucmd, - (option_msg && diag_msg) ? F_NORMAL : F_SILENT); + (option_msg && diag_msg) ? F_NORMAL : F_SILENT); if (status) { if (option_msg) { - err_print("%s failed\n", (cmd == SCMD_RESERVE) ? - "Reserve" : "Release"); + err_print("%s failed\n", (cmd == SCMD_RESERVE) ? + "Reserve" : "Release"); } } } @@ -2916,13 +2917,13 @@ scsi_extract_sense_info_descr(struct scsi_descr_sense_hdr *sdsp, int rqlen) */ result = (((diskaddr_t)isd->isd_information[0] << 56) | - ((diskaddr_t)isd->isd_information[1] << 48) | - ((diskaddr_t)isd->isd_information[2] << 40) | - ((diskaddr_t)isd->isd_information[3] << 32) | - ((diskaddr_t)isd->isd_information[4] << 24) | - ((diskaddr_t)isd->isd_information[5] << 16) | - ((diskaddr_t)isd->isd_information[6] << 8) | - ((diskaddr_t)isd->isd_information[7])); + ((diskaddr_t)isd->isd_information[1] << 48) | + ((diskaddr_t)isd->isd_information[2] << 40) | + ((diskaddr_t)isd->isd_information[3] << 32) | + ((diskaddr_t)isd->isd_information[4] << 24) | + ((diskaddr_t)isd->isd_information[5] << 16) | + ((diskaddr_t)isd->isd_information[6] << 8) | + ((diskaddr_t)isd->isd_information[7])); break; } @@ -2975,7 +2976,7 @@ apply_chg_list(int pageno, int pagsiz, uchar_t *curbits, while (chglist != NULL) { if (chglist->pageno == pageno && - chglist->byteno < pagsiz) { + chglist->byteno < pagsiz) { i = chglist->byteno; c = curbits[i]; switch (chglist->mode) { @@ -3288,16 +3289,16 @@ check_support_for_defects() rq = (struct scsi_extended_sense *)ucmd.uscsi_rqbuf; status = uscsi_cmd(cur_file, &ucmd, - (option_msg && diag_msg) ? F_NORMAL : F_SILENT); + (option_msg && diag_msg) ? F_NORMAL : F_SILENT); if (status != 0) { /* * check if read_defect_list_is_supported. */ if (ucmd.uscsi_rqstatus == STATUS_GOOD && - rq->es_key == KEY_ILLEGAL_REQUEST && - rq->es_add_code == INVALID_OPCODE) - return (0); + rq->es_key == KEY_ILLEGAL_REQUEST && + rq->es_add_code == INVALID_OPCODE) + return (0); } return (1); } @@ -3335,7 +3336,7 @@ scsi_format_without_defects() * Issue the format ioctl */ status = uscsi_cmd(cur_file, &ucmd, - (option_msg && diag_msg) ? F_NORMAL : F_SILENT); + (option_msg && diag_msg) ? F_NORMAL : F_SILENT); return (status); } diff --git a/usr/src/cmd/format/defect.c b/usr/src/cmd/format/defect.c index 537a854518..a2f77e1032 100644 --- a/usr/src/cmd/format/defect.c +++ b/usr/src/cmd/format/defect.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -132,8 +132,8 @@ read_list(struct defect_list *list) /* * Allocate space for the rest of the list. */ - size = LISTSIZE(list->header.count); - list->list = (struct defect_entry *)zalloc(size * SECSIZE); + size = deflist_size(cur_blksz, list->header.count); + list->list = (struct defect_entry *)zalloc(size * cur_blksz); /* * Try to read in the rest of the list. If there is an * error, or the checksum is wrong, this copy is corrupt. @@ -352,7 +352,7 @@ write_deflist(struct defect_list *list) /* * calculate how many sectors the defect list will occupy. */ - size = LISTSIZE(list->header.count); + size = deflist_size(cur_blksz, list->header.count); /* * Loop for each copy of the list to be written. Write * out the header of the list followed by the data. @@ -444,9 +444,9 @@ add_def(struct defect_entry *def, struct defect_list *list, int index) * sector, allocate the necessary space. */ count = list->header.count; - if (LISTSIZE(count + 1) > LISTSIZE(count)) + if (deflist_size(cur_blksz, count + 1) > deflist_size(cur_blksz, count)) list->list = (struct defect_entry *)rezalloc((void *)list->list, - LISTSIZE(count + 1) * SECSIZE); + deflist_size(cur_blksz, count + 1) * cur_blksz); /* * Slip all the defects after this one down one slot in the list. */ @@ -485,3 +485,22 @@ kill_deflist(struct defect_list *list) list->list = NULL; list->flags = 0; } + +/* + * This routine returns the defect list size + * according to the sector size. + */ +int +deflist_size(int secsz, int sz) +{ + int rval; + + if (secsz == 0) { + secsz = SECSIZE; + } + + rval = sz ? ((sz * sizeof (struct defect_entry) + + secsz - 1) / secsz) : 1; + + return (rval); +} diff --git a/usr/src/cmd/format/defect.h b/usr/src/cmd/format/defect.h index a917144068..7b3990ceee 100644 --- a/usr/src/cmd/format/defect.h +++ b/usr/src/cmd/format/defect.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,15 +19,13 @@ * CDDL HEADER END */ /* - * Copyright 1991-2002 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _DEFECT_H #define _DEFECT_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -82,16 +79,6 @@ struct defect_list { #define LISTCOUNT 2 /* - * This defines the size (in sectors) of the defect array given the number - * of defects in the array. It must be rounded to a sector boundary since - * that is the atomic disk size. We make a zero length list use up a - * sector because it is convenient to have malloc'd space in every - * non-null list. - */ -#define LISTSIZE(x) ((x) ? ((x) * sizeof (struct defect_entry) + \ - SECSIZE - 1) / SECSIZE : 1) - -/* * These defines are the flags for the defect list. */ #define LIST_DIRTY 0x01 /* List needs to be synced */ @@ -135,6 +122,15 @@ void add_def(struct defect_entry *def, struct defect_list *list, int index); void kill_deflist(struct defect_list *list); +/* + * This defines the size (in sectors) of the defect array given the number + * of defects in the array. It must be rounded to a sector boundary since + * that is the atomic disk size. We make a zero length list use up a + * sector because it is convenient to have malloc'd space in every + * non-null list. + */ +int deflist_size(int secsz, int sz); + #ifdef __cplusplus } #endif diff --git a/usr/src/cmd/format/disk_generic.c b/usr/src/cmd/format/disk_generic.c index 3aa205b3c0..d053660a04 100644 --- a/usr/src/cmd/format/disk_generic.c +++ b/usr/src/cmd/format/disk_generic.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -121,8 +121,8 @@ generic_rdwr(dir, fd, blkno, secnt, bufaddr, flags, xfercntp) offset_t tmpsec, status, tmpblk; int ret; - tmpsec = (offset_t)secnt * UBSIZE; - tmpblk = (offset_t)blkno * UBSIZE; + tmpsec = (offset_t)secnt * cur_blksz; + tmpblk = (offset_t)blkno * cur_blksz; #if defined(_FIRMWARE_NEEDS_FDISK) /* Use "p0" file to seek/read the data */ diff --git a/usr/src/cmd/format/global.h b/usr/src/cmd/format/global.h index fc3a25a938..241df1e3e5 100644 --- a/usr/src/cmd/format/global.h +++ b/usr/src/cmd/format/global.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -107,6 +107,7 @@ int dev_expert; /* enable for developer mode */ int cur_file; /* file descriptor for current disk */ int cur_flags; /* flags for current disk */ int cur_label; /* current label type */ +uint_t cur_blksz; /* currect disk block size */ struct disk_info *cur_disk; /* current disk */ struct disk_type *cur_dtype; /* current dtype */ struct ctlr_info *cur_ctlr; /* current ctlr */ diff --git a/usr/src/cmd/format/hardware_structs.h b/usr/src/cmd/format/hardware_structs.h index b72ebdf308..81bc40d202 100644 --- a/usr/src/cmd/format/hardware_structs.h +++ b/usr/src/cmd/format/hardware_structs.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -62,6 +62,8 @@ struct disk_info { char v_volume[LEN_DKL_VVOL]; /* volume name from label */ /* (no terminating null) */ + uint_t disk_lbasize; /* disk block size */ + }; #define NSPECIFICS 8 diff --git a/usr/src/cmd/format/io.c b/usr/src/cmd/format/io.c index 1aa2413c65..6e9e4064a9 100644 --- a/usr/src/cmd/format/io.c +++ b/usr/src/cmd/format/io.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -606,11 +606,11 @@ reprompt: fmt_print("[%llub, %llue, %llumb, %llugb, %llutb]", efi_deflt->end_sector, efi_deflt->start_sector + efi_deflt->end_sector - 1, - (efi_deflt->end_sector * DEV_BSIZE) / + (efi_deflt->end_sector * cur_blksz) / (1024 * 1024), - (efi_deflt->end_sector * DEV_BSIZE) / + (efi_deflt->end_sector * cur_blksz) / (1024 * 1024 * 1024), - (efi_deflt->end_sector * DEV_BSIZE) / + (efi_deflt->end_sector * cur_blksz) / ((uint64_t)1024 * 1024 * 1024 * 1024)); break; case FIO_OPINT: @@ -1518,13 +1518,13 @@ or g(gigabytes)\n"); fmt_print("Expecting up to %llu sectors,", cur_parts->etoc->efi_last_u_lba); fmt_print("or %llu megabytes,", - (cur_parts->etoc->efi_last_u_lba * DEV_BSIZE)/ + (cur_parts->etoc->efi_last_u_lba * cur_blksz)/ (1024 * 1024)); fmt_print("or %llu gigabytes\n", - (cur_parts->etoc->efi_last_u_lba * DEV_BSIZE)/ + (cur_parts->etoc->efi_last_u_lba * cur_blksz)/ (1024 * 1024 * 1024)); fmt_print("or %llu terabytes\n", - (cur_parts->etoc->efi_last_u_lba * DEV_BSIZE)/ + (cur_parts->etoc->efi_last_u_lba * cur_blksz)/ ((uint64_t)1024 * 1024 * 1024 * 1024)); break; } @@ -1676,7 +1676,7 @@ or g(gigabytes)\n"); break; } return (uint64_t)((float)nmegs * 1024.0 * - 1024.0 * 1024.0 * 1024.0 / DEV_BSIZE); + 1024.0 * 1024.0 * 1024.0 / cur_blksz); default: err_print( @@ -2102,6 +2102,7 @@ pr_diskline(disk, num) type->dtype_acyl, type->dtype_nhead, type->dtype_nsect); } else if ((type != NULL) && (disk->label_type == L_TYPE_EFI)) { + cur_blksz = disk->disk_lbasize; print_efi_string(type->vendor, type->product, type->revision, type->capacity); } else if (disk->disk_flags & DSK_RESERVED) { diff --git a/usr/src/cmd/format/label.c b/usr/src/cmd/format/label.c index 3f172c5806..4740baebb2 100644 --- a/usr/src/cmd/format/label.c +++ b/usr/src/cmd/format/label.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -270,11 +270,11 @@ write_label() { int error = 0, head, sec; struct dk_label label; - struct dk_label new_label; struct extvtoc vtoc; struct dk_geom geom; struct dk_gpt *vtoc64; int nbackups; + char *new_label; #if defined(_SUNOS_VTOC_8) int i; @@ -313,7 +313,8 @@ write_label() * Fill in a label structure with the geometry information. */ (void) memset((char *)&label, 0, sizeof (struct dk_label)); - (void) memset((char *)&new_label, 0, sizeof (struct dk_label)); + new_label = zalloc(cur_blksz); + label.dkl_pcyl = pcyl; label.dkl_ncyl = ncyl; label.dkl_acyl = acyl; @@ -358,10 +359,9 @@ write_label() #if defined(_SUNOS_VTOC_16) /* - * Also add in v_sectorsz, as the driver will. Everyone - * else is assuming DEV_BSIZE, so we do the same. + * Also add in v_sectorsz, as the driver will. */ - label.dkl_vtoc.v_sectorsz = DEV_BSIZE; + label.dkl_vtoc.v_sectorsz = cur_blksz; #endif /* defined(_SUNOS_VTOC_16) */ /* @@ -372,6 +372,7 @@ write_label() * Convert the label into a vtoc */ if (label_to_vtoc(&vtoc, &label) == -1) { + free(new_label); return (-1); } /* @@ -400,6 +401,7 @@ write_label() * is only for SCSI disks. */ if (SCSI && do_geometry_sanity_check() != 0) { + free(new_label); return (-1); } @@ -444,14 +446,15 @@ write_label() for (sec = 1; ((sec < BAD_LISTCNT * 2 + 1) && (sec < nsect)); sec += 2) { if ((*cur_ops->op_rdwr)(DIR_READ, cur_file, (diskaddr_t) - ((chs2bn(ncyl + acyl - 1, head, sec)) + solaris_offset), - 1, (caddr_t)&new_label, F_NORMAL, NULL)) { - err_print("Warning: error reading backup label.\n"); + ((chs2bn(ncyl + acyl - 1, head, sec)) + + solaris_offset), 1, new_label, F_NORMAL, NULL)) { + err_print("Warning: error reading" + "backup label.\n"); error = -1; } else { - if (bcmp((char *)&label, (char *)&new_label, + if (bcmp((char *)&label, new_label, sizeof (struct dk_label)) == 0) { - nbackups++; + nbackups++; } } } @@ -466,6 +469,7 @@ write_label() cur_disk->disk_flags |= DSK_LABEL; exit_critical(); + free(new_label); return (error); } @@ -578,7 +582,8 @@ get_disk_info(int fd, struct efi_info *label) err_print("Fetch Capacity failed\n"); return (-1); } - label->capacity = minf.dki_capacity * minf.dki_lbsize / 512; + label->capacity = + minf.dki_capacity * minf.dki_lbsize / cur_blksz; } else { label->capacity = capacity.sc_capacity; @@ -689,7 +694,7 @@ vtoc_to_label(struct dk_label *label, struct extvtoc *vtoc, /* * Sanity-check the vtoc */ - if (vtoc->v_sanity != VTOC_SANE || vtoc->v_sectorsz != DEV_BSIZE || + if (vtoc->v_sanity != VTOC_SANE || vtoc->v_nparts != V_NUMPAR) { return (-1); } @@ -881,7 +886,7 @@ label_to_vtoc(struct extvtoc *vtoc, struct dk_label *label) */ vtoc->v_sanity = VTOC_SANE; vtoc->v_version = V_VERSION; - vtoc->v_sectorsz = DEV_BSIZE; + vtoc->v_sectorsz = cur_blksz; vtoc->v_nparts = V_NUMPAR; (void) memcpy(vtoc->v_asciilabel, label->dkl_asciilabel, diff --git a/usr/src/cmd/format/main.c b/usr/src/cmd/format/main.c index 5d1d9c6c81..5cdb72a825 100644 --- a/usr/src/cmd/format/main.c +++ b/usr/src/cmd/format/main.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -365,6 +365,7 @@ init_globals(disk) cur_label = cur_disk->label_type; cur_ctlr = cur_disk->disk_ctlr; cur_parts = cur_disk->disk_parts; + cur_blksz = cur_disk->disk_lbasize; cur_ctype = cur_ctlr->ctlr_ctype; cur_ops = cur_ctype->ctype_ops; cur_flags = 0; @@ -439,8 +440,8 @@ init_globals(disk) /* * Allocate the buffers. */ - cur_buf = (void *) zalloc(BUF_SECTS * SECSIZE); - pattern_buf = (void *) zalloc(BUF_SECTS * SECSIZE); + cur_buf = (void *) zalloc(BUF_SECTS * cur_blksz); + pattern_buf = (void *) zalloc(BUF_SECTS * cur_blksz); /* * Tell the user which disk (s)he selected. diff --git a/usr/src/cmd/format/menu_analyze.c b/usr/src/cmd/format/menu_analyze.c index 2b18e3c327..e932c258c8 100644 --- a/usr/src/cmd/format/menu_analyze.c +++ b/usr/src/cmd/format/menu_analyze.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -183,12 +183,12 @@ a_print() * Loop through the data buffer. */ lines = 0; - for (i = 0; i < scan_size * SECSIZE / sizeof (int); i += 6) { + for (i = 0; i < scan_size * cur_blksz / sizeof (int); i += 6) { /* * Print the data. */ for (j = 0; j < 6; j++) - if (i + j < scan_size * SECSIZE / sizeof (int)) + if (i + j < scan_size * cur_blksz / sizeof (int)) fmt_print("0x%08x ", *((int *)((int *)cur_buf + i + j))); fmt_print("\n"); diff --git a/usr/src/cmd/format/menu_command.c b/usr/src/cmd/format/menu_command.c index c5b5ea930e..9c43d41ae0 100644 --- a/usr/src/cmd/format/menu_command.c +++ b/usr/src/cmd/format/menu_command.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -293,8 +293,8 @@ found: * Also, set partition table (best guess) too. */ if (!option_f && ncyl == 0 && nhead == 0 && nsect == 0 && - (disk->label_type != L_TYPE_EFI)) { - (void) c_type(); + (disk->label_type != L_TYPE_EFI)) { + (void) c_type(); } /* @@ -305,11 +305,11 @@ found: if ((cur_disk->label_type == L_TYPE_EFI) && (cur_disk->disk_parts->etoc->efi_flags & - EFI_GPT_PRIMARY_CORRUPT)) { - err_print("Reading the primary EFI GPT label "); - err_print("failed. Using backup label.\n"); - err_print("Use the 'backup' command to restore "); - err_print("the primary label.\n"); + EFI_GPT_PRIMARY_CORRUPT)) { + err_print("Reading the primary EFI GPT label "); + err_print("failed. Using backup label.\n"); + err_print("Use the 'backup' command to restore "); + err_print("the primary label.\n"); } #if defined(_SUNOS_VTOC_16) @@ -383,6 +383,7 @@ c_type() } else { auto_conf_choice = -1; } + i = first_disk; for (tptr = type; tptr != NULL; tptr = tptr->dtype_next) { /* @@ -396,7 +397,8 @@ c_type() continue; } if (tptr->dtype_asciilabel) - fmt_print(" %d. %s\n", i++, tptr->dtype_asciilabel); + fmt_print(" %d. %s\n", i++, + tptr->dtype_asciilabel); } other_choice = i; fmt_print(" %d. other\n", i); @@ -418,85 +420,89 @@ c_type() /* * User chose "auto configure". */ - (void) strcpy(x86_devname, cur_disk->disk_name); - switch (cur_disk->label_type) { - case L_TYPE_SOLARIS: - if ((tptr = auto_sense(cur_file, 1, &label)) == NULL) { - err_print("Auto configure failed\n"); - return (-1); - } - fmt_print("%s: configured with capacity of ", - cur_disk->disk_name); - nblks = (diskaddr_t)tptr->dtype_ncyl * tptr->dtype_nhead * - tptr->dtype_nsect; - scaled = bn2mb(nblks); - if (scaled > 1024.0) { - fmt_print("%1.2fGB\n", scaled/1024.0); - } else { - fmt_print("%1.2fMB\n", scaled); - } - fmt_print("<%s cyl %d alt %d hd %d sec %d>\n", - tptr->dtype_asciilabel, tptr->dtype_ncyl, - tptr->dtype_acyl, tptr->dtype_nhead, - tptr->dtype_nsect); - break; - case L_TYPE_EFI: - if ((tptr = auto_efi_sense(cur_file, &efi_info)) == NULL) { - err_print("Auto configure failed\n"); - return (-1); - } - fmt_print("%s: configured with capacity of ", - cur_disk->disk_name); - scaled = bn2mb(efi_info.capacity); - if (scaled > 1024.0) { - fmt_print("%1.2fGB\n", scaled/1024.0); - } else { - fmt_print("%1.2fMB\n", scaled); - } - print_efi_string(efi_info.vendor, efi_info.product, - efi_info.revision, efi_info.capacity); - fmt_print("\n"); - for (nparts = 0; nparts < cur_parts->etoc->efi_nparts; - nparts++) { - if (cur_parts->etoc->efi_parts[nparts].p_tag == - V_RESERVED) { - if (cur_parts->etoc->efi_parts[nparts].p_name) { - (void) strcpy(volname, - cur_parts->etoc->efi_parts[nparts].p_name); - volinit = 1; + (void) strcpy(x86_devname, cur_disk->disk_name); + switch (cur_disk->label_type) { + case L_TYPE_SOLARIS: + if ((tptr = auto_sense(cur_file, 1, &label)) == NULL) { + err_print("Auto configure failed\n"); + return (-1); + } + fmt_print("%s: configured with capacity of ", + cur_disk->disk_name); + nblks = (diskaddr_t)tptr->dtype_ncyl * + tptr->dtype_nhead * tptr->dtype_nsect; + scaled = bn2mb(nblks); + if (scaled > 1024.0) { + fmt_print("%1.2fGB\n", scaled/1024.0); + } else { + fmt_print("%1.2fMB\n", scaled); } + fmt_print("<%s cyl %d alt %d hd %d sec %d>\n", + tptr->dtype_asciilabel, tptr->dtype_ncyl, + tptr->dtype_acyl, tptr->dtype_nhead, + tptr->dtype_nsect); break; - } - } - enter_critical(); - if (delete_disk_type(cur_disk->disk_type) != 0) { - fmt_print("Autoconfiguration failed.\n"); - return (-1); - } - cur_disk->disk_type = tptr; - cur_disk->disk_parts = tptr->dtype_plist; - init_globals(cur_disk); - exit_critical(); - if (volinit) { - for (nparts = 0; nparts < cur_parts->etoc->efi_nparts; - nparts++) { - if (cur_parts->etoc->efi_parts[nparts].p_tag == - V_RESERVED) { - (void) strcpy( - cur_parts->etoc->efi_parts[nparts].p_name, + case L_TYPE_EFI: + if ((tptr = auto_efi_sense(cur_file, &efi_info)) + == NULL) { + err_print("Auto configure failed\n"); + return (-1); + } + fmt_print("%s: configured with capacity of ", + cur_disk->disk_name); + scaled = bn2mb(efi_info.capacity); + if (scaled > 1024.0) { + fmt_print("%1.2fGB\n", scaled/1024.0); + } else { + fmt_print("%1.2fMB\n", scaled); + } + cur_blksz = efi_info.e_parts->efi_lbasize; + print_efi_string(efi_info.vendor, efi_info.product, + efi_info.revision, efi_info.capacity); + fmt_print("\n"); + for (nparts = 0; nparts < cur_parts->etoc->efi_nparts; + nparts++) { + if (cur_parts->etoc->efi_parts[nparts].p_tag == + V_RESERVED) { + if (cur_parts->etoc->efi_parts[nparts]. + p_name) { + (void) strcpy(volname, + cur_parts->etoc->efi_parts + [nparts].p_name); + volinit = 1; + } + break; + } + } + enter_critical(); + if (delete_disk_type(cur_disk->disk_type) != 0) { + fmt_print("Autoconfiguration failed.\n"); + return (-1); + } + cur_disk->disk_type = tptr; + cur_disk->disk_parts = tptr->dtype_plist; + init_globals(cur_disk); + exit_critical(); + if (volinit) { + for (nparts = 0; nparts < + cur_parts->etoc->efi_nparts; nparts++) { + if (cur_parts->etoc->efi_parts[nparts].p_tag == + V_RESERVED) { + (void) strcpy( + cur_parts->etoc->efi_parts[nparts].p_name, volname); - (void) strlcpy(cur_disk->v_volume, volname, + (void) strlcpy(cur_disk->v_volume, volname, LEN_DKL_VVOL); - break; + break; + } + } } - } - } - return (0); - break; - default: + return (0); + break; + default: /* Should never happen */ return (-1); - } + } } else if ((index == other_choice) && (cur_label == L_TYPE_SOLARIS)) { /* * User chose "other". @@ -525,14 +531,13 @@ c_type() d->dtype_threshold = get_threshold(&d->dtype_options); d->dtype_prefetch_min = get_min_prefetch(&d->dtype_options); d->dtype_prefetch_max = get_max_prefetch(d->dtype_prefetch_min, - &d->dtype_options); + &d->dtype_options); d->dtype_bps = get_bps(); #if defined(sparc) d->dtype_dr_type = 0; #endif /* defined(sparc) */ d->dtype_asciilabel = get_asciilabel(); - /* * Add the new type to the list of possible types for * this controller. We lock out interrupts so the lists @@ -563,18 +568,18 @@ c_type() cur_parts->etoc->efi_last_lba = maxLBA; cur_parts->etoc->efi_last_u_lba = maxLBA - 34; for (i = 0; i < cur_parts->etoc->efi_nparts; i++) { - cur_parts->etoc->efi_parts[i].p_start = 0; - cur_parts->etoc->efi_parts[i].p_size = 0; - cur_parts->etoc->efi_parts[i].p_tag = V_UNASSIGNED; + cur_parts->etoc->efi_parts[i].p_start = 0; + cur_parts->etoc->efi_parts[i].p_size = 0; + cur_parts->etoc->efi_parts[i].p_tag = V_UNASSIGNED; } cur_parts->etoc->efi_parts[8].p_start = - maxLBA - 34 - (1024 * 16); + maxLBA - 34 - (1024 * 16); cur_parts->etoc->efi_parts[8].p_size = (1024 * 16); cur_parts->etoc->efi_parts[8].p_tag = V_RESERVED; if (write_label()) { - err_print("Write label failed\n"); + err_print("Write label failed\n"); } else { - cur_disk->disk_flags &= ~DSK_LABEL_DIRTY; + cur_disk->disk_flags &= ~DSK_LABEL_DIRTY; } return (0); } else { @@ -584,10 +589,10 @@ c_type() i = first_disk; tptr = type; while (i < index) { - if (tptr->dtype_asciilabel) { - i++; - } - tptr = tptr->dtype_next; + if (tptr->dtype_asciilabel) { + i++; + } + tptr = tptr->dtype_next; } if ((tptr->dtype_asciilabel == NULL) && (tptr->dtype_next != NULL)) { @@ -605,18 +610,19 @@ c_type() * running from a file. */ if ((tptr != oldtype) && - checkmount((diskaddr_t)-1, (diskaddr_t)-1)) { + checkmount((diskaddr_t)-1, (diskaddr_t)-1)) { err_print( - "Cannot set disk type while it has mounted partitions.\n\n"); + "Cannot set disk type while it has mounted " + "partitions.\n\n"); return (-1); } /* * check for partitions being used for swapping in format zone */ if ((tptr != oldtype) && - checkswap((diskaddr_t)-1, (diskaddr_t)-1)) { - err_print("Cannot set disk type while its partition are \ -currently being used for swapping.\n"); + checkswap((diskaddr_t)-1, (diskaddr_t)-1)) { + err_print("Cannot set disk type while its partition are " + "currently being used for swapping.\n"); return (-1); } @@ -625,11 +631,11 @@ currently being used for swapping.\n"); */ if ((tptr != oldtype) && - checkdevinuse(cur_disk->disk_name, (diskaddr_t)-1, - (diskaddr_t)-1, 0, 0)) { + checkdevinuse(cur_disk->disk_name, (diskaddr_t)-1, + (diskaddr_t)-1, 0, 0)) { err_print("Cannot set disk type while its " "partitions are currently in use.\n"); - return (-1); + return (-1); } /* * If the type selected is different from the previous type, @@ -742,8 +748,8 @@ c_current() fmt_print("<type unknown>\n"); } else if (cur_label == L_TYPE_SOLARIS) { fmt_print("<%s cyl %d alt %d hd %d sec %d>\n", - cur_dtype->dtype_asciilabel, ncyl, - acyl, nhead, nsect); + cur_dtype->dtype_asciilabel, ncyl, + acyl, nhead, nsect); } else if (cur_label == L_TYPE_EFI) { print_efi_string(cur_dtype->vendor, cur_dtype->product, cur_dtype->revision, @@ -753,13 +759,13 @@ c_current() fmt_print("%s\n", cur_disk->devfs_name); } else { fmt_print("%s%d: <", cur_ctlr->ctlr_dname, - cur_disk->disk_dkinfo.dki_unit); + cur_disk->disk_dkinfo.dki_unit); if (cur_dtype == NULL) { fmt_print("type unknown"); } else if (cur_label == L_TYPE_SOLARIS) { fmt_print("%s cyl %d alt %d hd %d sec %d", - cur_dtype->dtype_asciilabel, ncyl, - acyl, nhead, nsect); + cur_dtype->dtype_asciilabel, ncyl, + acyl, nhead, nsect); } else if (cur_label == L_TYPE_EFI) { print_efi_string(cur_dtype->vendor, cur_dtype->product, cur_dtype->revision, @@ -811,8 +817,8 @@ c_format() * can only be retrieved after formatting the disk. */ if ((cur_ctype->ctype_flags & CF_SCSI) && !EMBEDDED_SCSI && - (cur_ctype->ctype_flags & CF_DEFECTS) && - ! (cur_flags & DISK_FORMATTED)) { + (cur_ctype->ctype_flags & CF_DEFECTS) && + ! (cur_flags & DISK_FORMATTED)) { cur_list.flags |= LIST_RELOAD; } else if (cur_list.list == NULL && !EMBEDDED_SCSI) { @@ -827,25 +833,25 @@ c_format() */ ioparam.io_bounds.lower = start = 0; if (cur_label == L_TYPE_SOLARIS) { - if (cur_ctype->ctype_flags & CF_SCSI) { - ioparam.io_bounds.upper = end = datasects() - 1; - } else { - ioparam.io_bounds.upper = end = physsects() - 1; - } + if (cur_ctype->ctype_flags & CF_SCSI) { + ioparam.io_bounds.upper = end = datasects() - 1; + } else { + ioparam.io_bounds.upper = end = physsects() - 1; + } } else { - ioparam.io_bounds.upper = end = cur_parts->etoc->efi_last_lba; + ioparam.io_bounds.upper = end = cur_parts->etoc->efi_last_lba; } if (! (cur_ctlr->ctlr_flags & DKI_FMTVOL)) { deflt = ioparam.io_bounds.lower; start = input(FIO_BN, - "Enter starting block number", ':', - &ioparam, (int *)&deflt, DATA_INPUT); + "Enter starting block number", ':', + &ioparam, (int *)&deflt, DATA_INPUT); ioparam.io_bounds.lower = start; deflt = ioparam.io_bounds.upper; end = input(FIO_BN, - "Enter ending block number", ':', - &ioparam, (int *)&deflt, DATA_INPUT); + "Enter ending block number", ':', + &ioparam, (int *)&deflt, DATA_INPUT); } /* * Some disks can format tracks. Make sure the whole track is @@ -853,7 +859,7 @@ c_format() */ if (cur_ctlr->ctlr_flags & DKI_FMTTRK) { if (bn2s(start) != 0 || - bn2s(end) != sectors(bn2h(end)) - 1) { + bn2s(end) != sectors(bn2h(end)) - 1) { err_print("Controller requires formatting of "); err_print("entire tracks.\n"); return (-1); @@ -886,13 +892,22 @@ currently being used for swapping.\n"); */ if (checkdevinuse(cur_disk->disk_name, start, end, 0, 0)) { err_print("Cannot format disk while its partitions " - "are currently in use.\n"); + "are currently in use.\n"); + return (-1); + } + + if (cur_disk->disk_lbasize != DEV_BSIZE) { + fmt_print("Current disk sector size is %d Byte, format\n" + "will change the sector size to 512 Byte. ", + cur_disk->disk_lbasize); + if (check("Continue")) { return (-1); + } } if (SCSI && (format_time = scsi_format_time()) > 0) { fmt_print( - "Ready to format. Formatting cannot be interrupted\n" + "\nReady to format. Formatting cannot be interrupted\n" "and takes %d minutes (estimated). ", format_time); } else if (cur_dtype->dtype_options & SUP_FMTTIME) { @@ -913,7 +928,7 @@ currently being used for swapping.\n"); * ms. */ format_time = ((60000 / cur_dtype->dtype_rpm) +1) * - format_tracks + format_cyls * 7; + format_tracks + format_cyls * 7; /* * 20% done tick (sec) */ @@ -964,7 +979,7 @@ currently being used for swapping.\n"); */ clock = time((time_t *)0); fmt_print("Beginning format. The current time is %s\n", - ctime(&clock)); + ctime(&clock)); enter_critical(); /* * Mark the defect list dirty so it will be rewritten when we are @@ -980,15 +995,15 @@ currently being used for swapping.\n"); * dirty so it will be rewritten. */ if (cur_disk->label_type == L_TYPE_SOLARIS) { - if (start < totalsects() && end >= datasects()) { - if (cur_disk->disk_flags & DSK_LABEL) - cur_flags |= LABEL_DIRTY; - } + if (start < totalsects() && end >= datasects()) { + if (cur_disk->disk_flags & DSK_LABEL) + cur_flags |= LABEL_DIRTY; + } } else if (cur_disk->label_type == L_TYPE_EFI) { - if (start < 34) { - if (cur_disk->disk_flags & DSK_LABEL) - cur_flags |= LABEL_DIRTY; - } + if (start < 34) { + if (cur_disk->disk_flags & DSK_LABEL) + cur_flags |= LABEL_DIRTY; + } } if (start == 0) { cur_flags |= LABEL_DIRTY; @@ -1078,7 +1093,7 @@ c_repair() diskaddr_t bn; int status; u_ioparam_t ioparam; - char buf[SECSIZE]; + char *buf; int buf_is_good; int block_has_error; int i; @@ -1125,13 +1140,13 @@ c_repair() */ ioparam.io_bounds.lower = 0; if (cur_disk->label_type == L_TYPE_SOLARIS) { - ioparam.io_bounds.upper = physsects() - 1; + ioparam.io_bounds.upper = physsects() - 1; } else { - ioparam.io_bounds.upper = cur_parts->etoc->efi_last_lba; + ioparam.io_bounds.upper = cur_parts->etoc->efi_last_lba; } bn = input(FIO_BN, - "Enter absolute block number of defect", ':', - &ioparam, (int *)NULL, DATA_INPUT); + "Enter absolute block number of defect", ':', + &ioparam, (int *)NULL, DATA_INPUT); /* * Check to see if there is a mounted file system over the * specified sector. If there is, make sure the user is @@ -1156,6 +1171,9 @@ being used for swapping.\ncontinue")) return (-1); } + buf = zalloc((cur_disk->disk_lbasize == 0) ? + SECSIZE : cur_disk->disk_lbasize); + /* * Try to read the sector before repairing it. If we can * get good data out of it, we can write that data back @@ -1169,7 +1187,7 @@ being used for swapping.\ncontinue")) block_has_error = 1; for (i = 0; i < 5; i++) { status = (*cur_ops->op_rdwr)(DIR_READ, cur_file, bn, - 1, buf, (F_SILENT | F_ALLERRS), NULL); + 1, buf, (F_SILENT | F_ALLERRS), NULL); if (status) break; /* one of the tries failed */ } @@ -1177,6 +1195,7 @@ being used for swapping.\ncontinue")) block_has_error = 0; if (check("\ This block doesn't appear to be bad. Repair it anyway")) { + free(buf); return (0); } } @@ -1184,6 +1203,7 @@ This block doesn't appear to be bad. Repair it anyway")) { * Last chance... */ if (check("Ready to repair defect, continue")) { + free(buf); return (-1); } /* @@ -1194,7 +1214,7 @@ This block doesn't appear to be bad. Repair it anyway")) { buf_is_good = 0; for (i = 0; i < 5; i++) { status = (*cur_ops->op_rdwr)(DIR_READ, cur_file, bn, - 1, buf, F_SILENT, NULL); + 1, buf, F_SILENT, NULL); if (status == 0) { buf_is_good = 1; break; @@ -1229,13 +1249,13 @@ This block doesn't appear to be bad. Repair it anyway")) { */ fmt_print("ok.\n"); if (!buf_is_good) { - bzero(buf, SECSIZE); + bzero(buf, cur_disk->disk_lbasize); } status = (*cur_ops->op_rdwr)(DIR_WRITE, cur_file, bn, - 1, buf, (F_SILENT | F_ALLERRS), NULL); + 1, buf, (F_SILENT | F_ALLERRS), NULL); if (status == 0) { status = (*cur_ops->op_rdwr)(DIR_READ, cur_file, - bn, 1, buf, (F_SILENT | F_ALLERRS), NULL); + bn, 1, buf, (F_SILENT | F_ALLERRS), NULL); } if (status) { fmt_print("The new block %llu (", bn); @@ -1275,6 +1295,8 @@ This block doesn't appear to be bad. Repair it anyway")) { kill_deflist(&work_list); } exit_critical(); + free(buf); + /* * Return status. */ @@ -1304,9 +1326,9 @@ c_show() */ ioparam.io_bounds.lower = 0; if (cur_disk->label_type == L_TYPE_SOLARIS) { - ioparam.io_bounds.upper = physsects() - 1; + ioparam.io_bounds.upper = physsects() - 1; } else { - ioparam.io_bounds.upper = cur_parts->etoc->efi_last_lba; + ioparam.io_bounds.upper = cur_parts->etoc->efi_last_lba; } bn = input(FIO_BN, "Enter a disk block", ':', &ioparam, (int *)NULL, DATA_INPUT); @@ -1359,7 +1381,7 @@ c_label() /* Bleagh, too descriptive */ if (check_label_with_mount()) { err_print("Cannot label disk while it has " - "mounted partitions.\n\n"); + "mounted partitions.\n\n"); return (-1); } } @@ -1398,7 +1420,7 @@ c_label() */ if (cur_parts == NULL) { fmt_print("Current Partition Table is not set, " - "using default.\n"); + "using default.\n"); cur_disk->disk_parts = cur_parts = cur_dtype->dtype_plist; if (cur_parts == NULL) { err_print("No default available, cannot label.\n"); @@ -1411,53 +1433,55 @@ c_label() */ if (expert_mode) { #if defined(_SUNOS_VTOC_8) - int i; + int i; #endif - int choice; - u_ioparam_t ioparam; - struct extvtoc vtoc; - struct dk_label label; - struct dk_gpt *vtoc64; - struct efi_info efinfo; - struct disk_type *dptr; - - /* Ask user what label to use */ - fmt_print("[0] SMI Label\n"); - fmt_print("[1] EFI Label\n"); - ioparam.io_bounds.lower = 0; - ioparam.io_bounds.upper = 1; - if (cur_label == L_TYPE_SOLARIS) - deflt = 0; - else - deflt = 1; - defltptr = &deflt; - choice = input(FIO_INT, "Specify Label type", ':', - &ioparam, defltptr, DATA_INPUT); - if ((choice == 0) && (cur_label == L_TYPE_SOLARIS)) { - goto expert_end; - } else if ((choice == 1) && (cur_label == L_TYPE_EFI)) { - goto expert_end; - } - switch (choice) { - case 0: + int choice; + u_ioparam_t ioparam; + struct extvtoc vtoc; + struct dk_label label; + struct dk_gpt *vtoc64; + struct efi_info efinfo; + struct disk_type *dptr; + + /* Ask user what label to use */ + fmt_print("[0] SMI Label\n"); + fmt_print("[1] EFI Label\n"); + ioparam.io_bounds.lower = 0; + ioparam.io_bounds.upper = 1; + if (cur_label == L_TYPE_SOLARIS) + deflt = 0; + else + deflt = 1; + defltptr = &deflt; + choice = input(FIO_INT, "Specify Label type", ':', + &ioparam, defltptr, DATA_INPUT); + if ((choice == 0) && (cur_label == L_TYPE_SOLARIS)) { + goto expert_end; + } else if ((choice == 1) && (cur_label == L_TYPE_EFI)) { + goto expert_end; + } + switch (choice) { + case 0: /* * EFI label to SMI label */ if (cur_dtype->capacity > INFINITY) { - fmt_print("Warning: SMI labels only support up to 2 TB.\n"); + fmt_print("Warning: SMI labels only support up to " + "2 TB.\n"); } if (cur_disk->fdisk_part.systid == EFI_PMBR) { - fmt_print("Warning: This disk has an EFI label. Changing to" - " SMI label will erase all\ncurrent partitions.\n"); - if (check("Continue")) + fmt_print("Warning: This disk has an EFI label. " + "Changing to SMI label will erase all\n" + "current partitions.\n"); + if (check("Continue")) return (-1); #if defined(_FIRMWARE_NEEDS_FDISK) - fmt_print("You must use fdisk to delete the current " + fmt_print("You must use fdisk to delete the current " "EFI partition and create a new\n" "Solaris partition before you can convert the " "label.\n"); - return (-1); + return (-1); #endif } @@ -1509,7 +1533,7 @@ c_label() } - case 1: + case 1: /* * SMI label to EFI label */ @@ -1523,7 +1547,7 @@ c_label() } if (get_disk_info(cur_file, &efinfo) != 0) { - return (-1); + return (-1); } (void) memset((char *)&label, 0, sizeof (struct dk_label)); label.dkl_pcyl = pcyl; @@ -1536,21 +1560,21 @@ c_label() label.dkl_nsect = nsect; #if defined(_SUNOS_VTOC_8) for (i = 0; i < NDKMAP; i++) { - label.dkl_map[i] = cur_parts->pinfo_map[i]; + label.dkl_map[i] = cur_parts->pinfo_map[i]; } #endif /* defined(_SUNOS_VTOC_8) */ label.dkl_magic = DKL_MAGIC; label.dkl_vtoc = cur_parts->vtoc; if (label_to_vtoc(&vtoc, &label) == -1) { - return (-1); + return (-1); } if (SMI_vtoc_to_EFI(cur_file, &vtoc64) == -1) { - return (-1); + return (-1); } if (efi_write(cur_file, vtoc64) != 0) { - err_check(vtoc64); - err_print("Warning: error writing EFI.\n"); - return (-1); + err_check(vtoc64); + err_print("Warning: error writing EFI.\n"); + return (-1); } else { cur_disk->disk_flags &= ~DSK_LABEL_DIRTY; } @@ -1580,7 +1604,7 @@ c_label() (void) copy_solaris_part(&cur_disk->fdisk_part); return (0); - } + } } expert_end: @@ -1648,7 +1672,7 @@ c_defect() * display appropriate message. */ if ((cur_ops->op_ex_man == NULL) && (cur_ops->op_ex_cur == NULL) && - (cur_ops->op_create == NULL) && (cur_ops->op_wr_cur == NULL)) { + (cur_ops->op_create == NULL) && (cur_ops->op_wr_cur == NULL)) { err_print("Controller does not support defect management\n"); err_print("or disk supports automatic defect management.\n"); return (-1); @@ -1667,7 +1691,8 @@ c_defect() if ((work_list.list == NULL) && (cur_list.list != NULL)) { work_list.header = cur_list.header; work_list.list = (struct defect_entry *)zalloc( - LISTSIZE(work_list.header.count) * SECSIZE); + deflist_size(cur_blksz, work_list.header.count) * + cur_blksz); for (i = 0; i < work_list.header.count; i++) *(work_list.list + i) = *(cur_list.list + i); work_list.flags = cur_list.flags & LIST_PGLIST; @@ -1710,6 +1735,7 @@ c_backup() struct partition_info *parts, *plist; diskaddr_t bn; int sec, head, i; + char *buf; /* * There must be a current disk type (and therefore a current disk). @@ -1736,23 +1762,26 @@ c_backup() * the user is serious. */ if (cur_disk->label_type == L_TYPE_EFI) { - if (((cur_disk->disk_parts->etoc->efi_flags & - EFI_GPT_PRIMARY_CORRUPT) == 0) && - check("Disk has a primary label, still continue")) - return (-1); - fmt_print("Restoring primary label.\n"); - if (write_label()) { - err_print("Failed\n"); - return (-1); - } - return (0); + if (((cur_disk->disk_parts->etoc->efi_flags & + EFI_GPT_PRIMARY_CORRUPT) == 0) && + check("Disk has a primary label, still continue")) + return (-1); + fmt_print("Restoring primary label.\n"); + if (write_label()) { + err_print("Failed\n"); + return (-1); + } + return (0); } else if (((cur_disk->disk_flags & (DSK_LABEL | DSK_LABEL_DIRTY)) == - DSK_LABEL) && + DSK_LABEL) && (check("Disk has a primary label, still continue"))) { return (-1); } + + buf = zalloc(cur_blksz); fmt_print("Searching for backup labels..."); (void) fflush(stdout); + /* * Some disks have the backup labels in a strange place. */ @@ -1770,9 +1799,12 @@ c_backup() * Attempt to read it. */ if ((*cur_ops->op_rdwr)(DIR_READ, cur_file, bn, - 1, (char *)&label, F_NORMAL, NULL)) { + 1, buf, F_NORMAL, NULL)) { continue; } + + (void *) memcpy((char *)&label, buf, sizeof (struct dk_label)); + /* * Verify that it is a reasonable label. */ @@ -1801,15 +1833,17 @@ c_backup() fmt_print("\ Unknown disk type in backup label\n"); exit_critical(); + free(buf); return (-1); } fmt_print("Backup label claims different type:\n"); fmt_print(" <%s cyl %d alt %d hd %d sec %d>\n", - label.dkl_asciilabel, label.dkl_ncyl, - label.dkl_acyl, label.dkl_nhead, - label.dkl_nsect); + label.dkl_asciilabel, label.dkl_ncyl, + label.dkl_acyl, label.dkl_nhead, + label.dkl_nsect); if (check("Continue")) { exit_critical(); + free(buf); return (-1); } cur_dtype = dtype; @@ -1828,7 +1862,7 @@ Unknown disk type in backup label\n"); */ if (parts == NULL) { parts = (struct partition_info *) - zalloc(sizeof (struct partition_info)); + zalloc(sizeof (struct partition_info)); plist = dtype->dtype_plist; if (plist == NULL) dtype->dtype_plist = parts; @@ -1863,22 +1897,28 @@ Unknown disk type in backup label\n"); */ if (EMBEDDED_SCSI) { fmt_print("Restoring primary label.\n"); - if (write_label()) + if (write_label()) { + free(buf); return (-1); + } } else { fmt_print("Restoring primary label and defect list.\n"); - if (write_label()) + if (write_label()) { + free(buf); return (-1); + } if (cur_list.list != NULL) write_deflist(&cur_list); } fmt_print("\n"); + free(buf); return (0); } /* * If we didn't find any backup labels, say so. */ fmt_print("not found.\n\n"); + free(buf); return (0); } @@ -1894,8 +1934,8 @@ c_verify_efi() status = read_efi_label(cur_file, &efi_info); if (status != 0) { - err_print("Warning: Could not read label.\n"); - return (-1); + err_print("Warning: Could not read label.\n"); + return (-1); } if (cur_parts->etoc->efi_flags & EFI_GPT_PRIMARY_CORRUPT) { err_print("Reading the primary EFI GPT label "); @@ -1906,20 +1946,20 @@ c_verify_efi() tmp_pinfo.etoc = efi_info.e_parts; fmt_print("\n"); if (cur_parts->etoc->efi_parts[8].p_name) { - fmt_print("Volume name = <%8s>\n", - cur_parts->etoc->efi_parts[8].p_name); + fmt_print("Volume name = <%8s>\n", + cur_parts->etoc->efi_parts[8].p_name); } else { - fmt_print("Volume name = < >\n"); + fmt_print("Volume name = < >\n"); } fmt_print("ascii name = "); print_efi_string(efi_info.vendor, efi_info.product, efi_info.revision, efi_info.capacity); fmt_print("\n"); - fmt_print("bytes/sector = %d\n", DEV_BSIZE); + fmt_print("bytes/sector = %d\n", cur_blksz); fmt_print("sectors = %llu\n", cur_parts->etoc->efi_last_lba); fmt_print("accessible sectors = %llu\n", - cur_parts->etoc->efi_last_u_lba); + cur_parts->etoc->efi_last_u_lba); print_map(&tmp_pinfo); return (0); @@ -1941,6 +1981,7 @@ c_verify() int p_label_found = 0; int b_label_found = 0; char id_str[128]; + char *buf; /* * There must be a current disk type (and therefore a current disk). @@ -1966,7 +2007,7 @@ c_verify() * Branch off here if the disk is EFI labelled. */ if (cur_label == L_TYPE_EFI) { - return (c_verify_efi()); + return (c_verify_efi()); } /* * Attempt to read the primary label. @@ -1985,7 +2026,7 @@ c_verify() (void) strncpy(id_str, p_label.dkl_asciilabel, 128); if ((!checklabel((struct dk_label *)&p_label)) || - (trim_id(p_label.dkl_asciilabel))) { + (trim_id(p_label.dkl_asciilabel))) { err_print("\ Warning: Primary label appears to be corrupt.\n"); p_label_bad = 1; @@ -1995,10 +2036,10 @@ Warning: Primary label appears to be corrupt.\n"); * Make sure it matches current label */ if ((!dtype_match(&p_label, cur_dtype)) || - (!parts_match(&p_label, cur_parts))) { + (!parts_match(&p_label, cur_parts))) { err_print("\ Warning: Primary label on disk appears to be different from\ncurrent label.\n"); - p_label_bad = 1; + p_label_bad = 1; } } } @@ -2011,6 +2052,8 @@ Warning: Primary label on disk appears to be different from\ncurrent label.\n"); head = 2; else head = nhead - 1; + + buf = zalloc(cur_blksz); /* * Loop through each copy of the backup label. */ @@ -2021,8 +2064,12 @@ Warning: Primary label on disk appears to be different from\ncurrent label.\n"); * Attempt to read it. */ if ((*cur_ops->op_rdwr)(DIR_READ, cur_file, bn, - 1, (char *)&b_label, F_NORMAL, NULL)) + 1, buf, F_NORMAL, NULL)) continue; + + (void *) memcpy((char *)&b_label, buf, + sizeof (struct dk_label)); + /* * Verify that it is a reasonable label. */ @@ -2043,11 +2090,11 @@ Warning: Primary label on disk appears to be different from\ncurrent label.\n"); */ if (p_label_found) { if ((strcmp(b_label.dkl_asciilabel, - p_label.dkl_asciilabel) != 0) || - (b_label.dkl_ncyl != p_label.dkl_ncyl) || - (b_label.dkl_acyl != p_label.dkl_acyl) || - (b_label.dkl_nhead != p_label.dkl_nhead) || - (b_label.dkl_nsect != p_label.dkl_nsect)) { + p_label.dkl_asciilabel) != 0) || + (b_label.dkl_ncyl != p_label.dkl_ncyl) || + (b_label.dkl_acyl != p_label.dkl_acyl) || + (b_label.dkl_nhead != p_label.dkl_nhead) || + (b_label.dkl_nsect != p_label.dkl_nsect)) { b_label_bad = 1; } else { for (i = 0; i < NDKMAP; i++) { @@ -2062,13 +2109,16 @@ Warning: Primary label on disk appears to be different from\ncurrent label.\n"); #elif defined(_SUNOS_VTOC_16) if ((b_label.dkl_vtoc.v_part[i].p_tag != - p_label.dkl_vtoc.v_part[i].p_tag) || - (b_label.dkl_vtoc.v_part[i].p_flag != - p_label.dkl_vtoc.v_part[i].p_flag) || - (b_label.dkl_vtoc.v_part[i].p_start != - p_label.dkl_vtoc.v_part[i].p_start) || - (b_label.dkl_vtoc.v_part[i].p_size != - p_label.dkl_vtoc.v_part[i].p_size)) { + p_label.dkl_vtoc.v_part[i].p_tag) || + (b_label.dkl_vtoc.v_part[i].p_flag + != p_label.dkl_vtoc.v_part[i]. + p_flag) || + (b_label.dkl_vtoc.v_part[i].p_start + != p_label.dkl_vtoc.v_part[i]. + p_start) || + (b_label.dkl_vtoc.v_part[i].p_size + != p_label.dkl_vtoc.v_part[i]. + p_size)) { b_label_bad = 1; break; } @@ -2104,6 +2154,7 @@ Warning: Check the current partitioning and 'label' the disk or use the\n\ fmt_print("\nBackup label contents:\n"); label = &b_label; } else { + free(buf); return (0); } @@ -2119,9 +2170,9 @@ Warning: Check the current partitioning and 'label' the disk or use the\n\ #elif defined(_SUNOS_VTOC_16) tmp_pinfo.pinfo_map[i].dkl_cylno = - label->dkl_vtoc.v_part[i].p_start / spc(); + label->dkl_vtoc.v_part[i].p_start / spc(); tmp_pinfo.pinfo_map[i].dkl_nblk = - label->dkl_vtoc.v_part[i].p_size; + label->dkl_vtoc.v_part[i].p_size; #else #error No VTOC layout defined. #endif /* defined(_SUNOS_VTOC_8) */ @@ -2143,6 +2194,7 @@ Warning: Check the current partitioning and 'label' the disk or use the\n\ fmt_print("nsect = %4d\n", label->dkl_nsect); print_map(&tmp_pinfo); + free(buf); return (0); } @@ -2323,9 +2375,9 @@ being used for swapping.\n\n"); bcopy(volname, cur_disk->v_volume, min((int)strlen(volname), LEN_DKL_VVOL)); if (cur_label == L_TYPE_EFI) { - bzero(cur_parts->etoc->efi_parts[8].p_name, LEN_DKL_VVOL); - bcopy(volname, cur_parts->etoc->efi_parts[8].p_name, - LEN_DKL_VVOL); + bzero(cur_parts->etoc->efi_parts[8].p_name, LEN_DKL_VVOL); + bcopy(volname, cur_parts->etoc->efi_parts[8].p_name, + LEN_DKL_VVOL); } /* * Write the labels out (this will also notify unix) and diff --git a/usr/src/cmd/format/menu_defect.c b/usr/src/cmd/format/menu_defect.c index 9a31134ec9..55388253ae 100644 --- a/usr/src/cmd/format/menu_defect.c +++ b/usr/src/cmd/format/menu_defect.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -92,7 +92,8 @@ d_restore() if (cur_list.list != NULL) { work_list.header = cur_list.header; work_list.list = (struct defect_entry *)zalloc( - LISTSIZE(work_list.header.count) * SECSIZE); + deflist_size(cur_blksz, work_list.header.count) * + cur_blksz); for (i = 0; i < work_list.header.count; i++) *(work_list.list + i) = *(cur_list.list + i); } @@ -230,7 +231,7 @@ and may take a long while. Continue")) fmt_print("Extraction complete.\n"); fmt_print( "Working list updated, total of %d defects.\n\n", - work_list.header.count); + work_list.header.count); } else { fmt_print("Extraction failed.\n\n"); } @@ -277,7 +278,7 @@ d_add() ioparam.io_bounds.lower = 0; ioparam.io_bounds.upper = 1; type = input(FIO_INT, "Select input format (enter its number)", ':', - &ioparam, &deflt, DATA_INPUT); + &ioparam, &deflt, DATA_INPUT); fmt_print("\nEnter Control-C to terminate.\n"); loop: if (type) { @@ -288,9 +289,9 @@ loop: def.bfi = def.nbits = UNKNOWN; ioparam.io_bounds.lower = 0; if (cur_disk->label_type == L_TYPE_SOLARIS) { - ioparam.io_bounds.upper = physsects() - 1; + ioparam.io_bounds.upper = physsects() - 1; } else { - ioparam.io_bounds.upper = cur_parts->etoc->efi_last_lba; + ioparam.io_bounds.upper = cur_parts->etoc->efi_last_lba; } bn = input(FIO_BN, "Enter defective block number", ':', &ioparam, (int *)NULL, DATA_INPUT); @@ -349,7 +350,7 @@ loop: work_list.header.magicno = (uint_t)DEFECT_MAGIC; work_list.header.count = 0; work_list.list = (struct defect_entry *)zalloc( - LISTSIZE(0) * SECSIZE); + deflist_size(cur_blksz, 0) * cur_blksz); } /* * Add the defect to the working list. @@ -420,9 +421,11 @@ d_delete() * If the size of the list in sectors has changed, reallocate * the list to shrink it appropriately. */ - if (LISTSIZE(count - 1) < LISTSIZE(count)) + if (deflist_size(cur_blksz, count - 1) < + deflist_size(cur_blksz, count)) work_list.list = (struct defect_entry *)rezalloc( - (void *)work_list.list, LISTSIZE(count - 1) * SECSIZE); + (void *)work_list.list, + deflist_size(cur_blksz, count - 1) * cur_blksz); /* * Decrement the defect count. */ @@ -488,7 +491,7 @@ d_print() * before going on. */ if (one_line || - (!nomore && ((i + 1) % (tty_lines - 1) == 0))) { + (!nomore && ((i + 1) % (tty_lines - 1) == 0))) { /* * Get the next character. */ @@ -574,8 +577,8 @@ d_dump() * Print a header containing the magic number, count, and checksum. */ (void) fprintf(fptr, "0x%08x%8d 0x%08x\n", - work_list.header.magicno, - work_list.header.count, work_list.header.cksum); + work_list.header.magicno, + work_list.header.count, work_list.header.cksum); /* * Loop through each defect in the working list. Write the * defect info to the defect file. @@ -583,8 +586,8 @@ d_dump() for (i = 0; i < work_list.header.count; i++) { dptr = work_list.list + i; (void) fprintf(fptr, "%4d%8d%7d%8d%8d%8d\n", - i+1, dptr->cyl, dptr->head, - dptr->bfi, dptr->nbits, dptr->sect); + i+1, dptr->cyl, dptr->head, + dptr->bfi, dptr->nbits, dptr->sect); } fmt_print("defect file updated, total of %d defects.\n", i); /* @@ -663,13 +666,13 @@ d_load() * Scan in the header. */ items = fscanf(fptr, "0x%x%d 0x%x\n", &magicno, - &count, (uint_t *)&cksum); + &count, (uint_t *)&cksum); /* * If the header is wrong, this isn't a good defect file. */ if (items != 3 || count < 0 || (magicno != (uint_t)DEFECT_MAGIC && - magicno != (uint_t)NO_CHECKSUM)) { + magicno != (uint_t)NO_CHECKSUM)) { err_print("Defect file is corrupted.\n"); status = -1; goto out; @@ -690,8 +693,8 @@ d_load() /* * Allocate space for the new list. */ - work_list.list = (struct defect_entry *)zalloc(LISTSIZE(count) * - SECSIZE); + work_list.list = (struct defect_entry *)zalloc( + deflist_size(cur_blksz, count) * cur_blksz); /* * Mark the working list dirty since we are modifying it. */ @@ -806,14 +809,14 @@ commit_list() work_list.header.magicno = (uint_t)DEFECT_MAGIC; work_list.header.count = 0; work_list.list = (struct defect_entry *)zalloc( - LISTSIZE(0) * SECSIZE); + deflist_size(cur_blksz, 0) * cur_blksz); } /* * Copy the working list into the current list. */ cur_list.header = work_list.header; cur_list.list = (struct defect_entry *)zalloc( - LISTSIZE(cur_list.header.count) * SECSIZE); + deflist_size(cur_blksz, cur_list.header.count) * cur_blksz); for (i = 0; i < cur_list.header.count; i++) *(cur_list.list + i) = *(work_list.list + i); /* diff --git a/usr/src/cmd/format/menu_fdisk.c b/usr/src/cmd/format/menu_fdisk.c index 4ebadee5ab..e1affd636a 100644 --- a/usr/src/cmd/format/menu_fdisk.c +++ b/usr/src/cmd/format/menu_fdisk.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -274,11 +274,11 @@ open_cur_file(int mode) char pbuf[MAXPATHLEN]; switch (mode) { - case FD_USE_P0_PATH: + case FD_USE_P0_PATH: (void) get_pname(&pbuf[0]); dkpath = pbuf; break; - case FD_USE_CUR_DISK_PATH: + case FD_USE_CUR_DISK_PATH: if (cur_disk->fdisk_part.systid == SUNIXOS || cur_disk->fdisk_part.systid == SUNIXOS2) { (void) get_sname(&pbuf[0]); @@ -287,7 +287,7 @@ open_cur_file(int mode) dkpath = cur_disk->disk_path; } break; - default: + default: err_print("Error: Invalid mode option for opening cur_file\n"); fullabort(); } @@ -388,7 +388,7 @@ update_cur_parts() for (i = 0; i < NDKMAP; i++) { #if defined(_SUNOS_VTOC_16) if (cur_parts->vtoc.v_part[i].p_tag && - cur_parts->vtoc.v_part[i].p_tag != V_ALTSCTR) { + cur_parts->vtoc.v_part[i].p_tag != V_ALTSCTR) { cur_parts->vtoc.v_part[i].p_start = 0; cur_parts->vtoc.v_part[i].p_size = 0; @@ -396,9 +396,9 @@ update_cur_parts() cur_parts->pinfo_map[i].dkl_nblk = 0; cur_parts->pinfo_map[i].dkl_cylno = 0; cur_parts->vtoc.v_part[i].p_tag = - default_vtoc_map[i].p_tag; + default_vtoc_map[i].p_tag; cur_parts->vtoc.v_part[i].p_flag = - default_vtoc_map[i].p_flag; + default_vtoc_map[i].p_flag; #if defined(_SUNOS_VTOC_16) } #endif @@ -412,14 +412,14 @@ update_cur_parts() cur_parts->pinfo_map[I_PARTITION].dkl_nblk = spc(); cur_parts->pinfo_map[I_PARTITION].dkl_cylno = 0; cur_parts->vtoc.v_part[C_PARTITION].p_start = - cur_parts->pinfo_map[C_PARTITION].dkl_cylno * nhead * nsect; + cur_parts->pinfo_map[C_PARTITION].dkl_cylno * nhead * nsect; cur_parts->vtoc.v_part[C_PARTITION].p_size = - cur_parts->pinfo_map[C_PARTITION].dkl_nblk; + cur_parts->pinfo_map[C_PARTITION].dkl_nblk; cur_parts->vtoc.v_part[I_PARTITION].p_start = - cur_parts->pinfo_map[I_PARTITION].dkl_cylno; + cur_parts->pinfo_map[I_PARTITION].dkl_cylno; cur_parts->vtoc.v_part[I_PARTITION].p_size = - cur_parts->pinfo_map[I_PARTITION].dkl_nblk; + cur_parts->pinfo_map[I_PARTITION].dkl_nblk; #endif /* defined(_SUNOS_VTOC_16) */ parts = cur_dtype->dtype_plist; @@ -438,18 +438,33 @@ get_solaris_part(int fd, struct ipart *ipart) int i; struct ipart ip; int status; + char *mbr; char *bootptr; struct dk_label update_label; (void) lseek(fd, 0, 0); - status = read(fd, (caddr_t)&boot_sec, NBPSCTR); - if (status != NBPSCTR) { + /* + * We may get mbr of different size, but the first 512 bytes + * are valid information. + */ + mbr = malloc(cur_blksz); + if (mbr == NULL) { + err_print("No memory available.\n"); + return (-1); + } + status = read(fd, mbr, cur_blksz); + + if (status != cur_blksz) { err_print("Bad read of fdisk partition. Status = %x\n", status); err_print("Cannot read fdisk partition information.\n"); + free(mbr); return (-1); } + (void) memcpy(&boot_sec, mbr, sizeof (struct mboot)); + free(mbr); + for (i = 0; i < FD_NUMPART; i++) { int ipc; @@ -478,8 +493,8 @@ get_solaris_part(int fd, struct ipart *ipart) #ifdef DEBUG else { err_print("Critical geometry values are zero:\n" - "\tnhead = %d; nsect = %d\n", nhead, - nsect); + "\tnhead = %d; nsect = %d\n", nhead, + nsect); } #endif /* DEBUG */ @@ -555,6 +570,7 @@ get_solaris_part(int fd, struct ipart *ipart) nsect = cur_dtype->dtype_nsect; nhead = cur_dtype->dtype_nhead; } + return (0); } @@ -565,6 +581,7 @@ copy_solaris_part(struct ipart *ipart) int status, i, fd; struct mboot mboot; + char *mbr; struct ipart ip; char buf[MAXPATHLEN]; char *bootptr; @@ -574,7 +591,7 @@ copy_solaris_part(struct ipart *ipart) if (stat(buf, &statbuf) == -1 || !S_ISCHR(statbuf.st_mode) || ((cur_label == L_TYPE_EFI) && - (cur_disk->disk_flags & DSK_LABEL_DIRTY))) { + (cur_disk->disk_flags & DSK_LABEL_DIRTY))) { /* * Make sure to reset solaris_offset to zero if it is * previously set by a selected disk that @@ -595,14 +612,26 @@ copy_solaris_part(struct ipart *ipart) return (-1); } - status = read(fd, (caddr_t)&mboot, sizeof (struct mboot)); + /* + * We may get mbr of different size, but the first 512 bytes + * are valid information. + */ + mbr = malloc(cur_blksz); + if (mbr == NULL) { + err_print("No memory available.\n"); + return (-1); + } + status = read(fd, mbr, cur_blksz); - if (status != sizeof (struct mboot)) { + if (status != cur_blksz) { err_print("Bad read of fdisk partition.\n"); (void) close(fd); + free(mbr); return (-1); } + (void) memcpy(&mboot, mbr, sizeof (struct mboot)); + for (i = 0; i < FD_NUMPART; i++) { int ipc; @@ -631,8 +660,8 @@ copy_solaris_part(struct ipart *ipart) #ifdef DEBUG else { err_print("Critical geometry values are zero:\n" - "\tnhead = %d; nsect = %d\n", nhead, - nsect); + "\tnhead = %d; nsect = %d\n", nhead, + nsect); } #endif /* DEBUG */ @@ -641,8 +670,8 @@ copy_solaris_part(struct ipart *ipart) } (void) close(fd); + free(mbr); return (0); - } #if defined(_FIRMWARE_NEEDS_FDISK) @@ -652,24 +681,36 @@ auto_solaris_part(struct dk_label *label) int status, i, fd; struct mboot mboot; + char *mbr; struct ipart ip; char *bootptr; char pbuf[MAXPATHLEN]; - (void) get_pname(&pbuf[0]); if ((fd = open_disk(pbuf, O_RDONLY)) < 0) { err_print("Error: can't open selected disk '%s'.\n", pbuf); return (-1); } - status = read(fd, (caddr_t)&mboot, sizeof (struct mboot)); + /* + * We may get mbr of different size, but the first 512 bytes + * are valid information. + */ + mbr = malloc(cur_blksz); + if (mbr == NULL) { + err_print("No memory available.\n"); + return (-1); + } + status = read(fd, mbr, cur_blksz); - if (status != sizeof (struct mboot)) { + if (status != cur_blksz) { err_print("Bad read of fdisk partition.\n"); + free(mbr); return (-1); } + (void) memcpy(&mboot, mbr, sizeof (struct mboot)); + for (i = 0; i < FD_NUMPART; i++) { int ipc; @@ -697,11 +738,11 @@ auto_solaris_part(struct dk_label *label) #ifdef DEBUG else { err_print("Critical label fields aren't " - "non-zero:\n" - "\tlabel->dkl_nhead = %d; " - "label->dkl_nsect = " - "%d\n", label->dkl_nhead, - label->dkl_nsect); + "non-zero:\n" + "\tlabel->dkl_nhead = %d; " + "label->dkl_nsect = " + "%d\n", label->dkl_nhead, + label->dkl_nsect); } #endif /* DEBUG */ @@ -711,7 +752,7 @@ auto_solaris_part(struct dk_label *label) } (void) close(fd); - + free(mbr); return (0); } #endif /* defined(_FIRMWARE_NEEDS_FDISK) */ @@ -739,9 +780,9 @@ good_fdisk() } else { err_print("WARNING - "); err_print("This disk may be in use by an application " - "that has\n\t modified the fdisk table. Ensure " - "that this disk is\n\t not currently in use " - "before proceeding to use fdisk.\n"); + "that has\n\t modified the fdisk table. Ensure " + "that this disk is\n\t not currently in use " + "before proceeding to use fdisk.\n"); return (0); } } diff --git a/usr/src/cmd/format/misc.c b/usr/src/cmd/format/misc.c index f148cc3115..55ca2e80a8 100644 --- a/usr/src/cmd/format/misc.c +++ b/usr/src/cmd/format/misc.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -867,7 +867,7 @@ bn2mb(uint64_t nblks) float n; n = (float)nblks / 1024.0; - return ((n / 1024.0) * DEV_BSIZE); + return ((n / 1024.0) * cur_blksz); } @@ -876,7 +876,7 @@ mb2bn(float mb) { diskaddr_t n; - n = (diskaddr_t)(mb * 1024.0 * (1024.0 / DEV_BSIZE)); + n = (diskaddr_t)(mb * 1024.0 * (1024.0 / cur_blksz)); return (n); } @@ -886,7 +886,7 @@ bn2gb(uint64_t nblks) float n; n = (float)nblks / (1024.0 * 1024.0); - return ((n/1024.0) * DEV_BSIZE); + return ((n/1024.0) * cur_blksz); } @@ -896,7 +896,7 @@ bn2tb(uint64_t nblks) float n; n = (float)nblks / (1024.0 * 1024.0 * 1024.0); - return ((n/1024.0) * DEV_BSIZE); + return ((n/1024.0) * cur_blksz); } diskaddr_t @@ -904,7 +904,7 @@ gb2bn(float gb) { diskaddr_t n; - n = (diskaddr_t)(gb * 1024.0 * 1024.0 * (1024.0 / DEV_BSIZE)); + n = (diskaddr_t)(gb * 1024.0 * 1024.0 * (1024.0 / cur_blksz)); return (n); } diff --git a/usr/src/cmd/format/prompts.c b/usr/src/cmd/format/prompts.c index ce87f06349..e6ef368bbb 100644 --- a/usr/src/cmd/format/prompts.c +++ b/usr/src/cmd/format/prompts.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,12 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * This file contains functions to prompt the user for various * disk characteristics. By isolating these into functions, @@ -196,7 +193,7 @@ get_bpt(n_sects, options) *options |= SUP_BPT; ioparam.io_bounds.lower = 1; ioparam.io_bounds.upper = INFINITY; - deflt = n_sects * SECSIZE; + deflt = n_sects * cur_blksz; return (input(FIO_INT, "Enter number of bytes/track", ':', &ioparam, &deflt, DATA_INPUT)); } @@ -435,7 +432,7 @@ get_bps() ioparam.io_bounds.upper = MAX_BPS; deflt = AVG_BPS; return (input(FIO_INT, "Enter bytes per sector", - ':', &ioparam, &deflt, DATA_INPUT)); + ':', &ioparam, &deflt, DATA_INPUT)); } return (0); diff --git a/usr/src/cmd/format/startup.c b/usr/src/cmd/format/startup.c index 99aa8d9d34..fd8e035688 100644 --- a/usr/src/cmd/format/startup.c +++ b/usr/src/cmd/format/startup.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1607,6 +1607,12 @@ add_device_to_disklist(char *devname, char *devpath) } } + if (ioctl(search_file, DKIOCGMEDIAINFO, &mediainfo) == -1) { + cur_blksz = DEV_BSIZE; + } else { + cur_blksz = mediainfo.dki_lbsize; + } + /* * If the type of disk is one we don't know about, * add it to the list. @@ -1708,8 +1714,11 @@ add_device_to_disklist(char *devname, char *devpath) * generic check for reserved disks here, including intel disks. */ if (dkinfo.dki_ctype == DKC_SCSI_CCS) { + char *first_sector; + + first_sector = zalloc(cur_blksz); i = scsi_rdwr(DIR_READ, search_file, (diskaddr_t)0, - 1, (char *)&search_label, F_SILENT, NULL); + 1, first_sector, F_SILENT, NULL); switch (i) { case DSK_RESERVED: access_flags |= DSK_RESERVED; @@ -1720,6 +1729,7 @@ add_device_to_disklist(char *devname, char *devpath) default: break; } + free(first_sector); } #endif /* defined(sparc) */ @@ -1751,6 +1761,11 @@ add_device_to_disklist(char *devname, char *devpath) search_disk->disk_name = alloc_string(devname); search_disk->disk_path = alloc_string(devpath); + /* + * Remember the lba size of the disk + */ + search_disk->disk_lbasize = cur_blksz; + (void) strcpy(x86_devname, devname); /* diff --git a/usr/src/cmd/fs.d/fsck.c b/usr/src/cmd/fs.d/fsck.c index 61e0da1622..18e3fe332b 100644 --- a/usr/src/cmd/fs.d/fsck.c +++ b/usr/src/cmd/fs.d/fsck.c @@ -19,16 +19,13 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ - -#pragma ident "%Z%%M% %I% %E% SMI" - #include <stdio.h> #include <errno.h> #include <limits.h> @@ -39,9 +36,12 @@ #include <sys/wait.h> #include <sys/vfstab.h> #include <sys/mntent.h> +#include <sys/sysmacros.h> #include <locale.h> #include <libintl.h> +#include <sys/dkio.h> +#define DEV_BSIZE 512 #define ARGV_MAX 16 #define FSTYPE_MAX 8 #define VFS_PATH "/usr/lib/fs" @@ -217,10 +217,13 @@ main(int argc, char *argv[]) int questflg = 0, Fflg = 0, Vflg = 0, sanity = 0; char *subopt; FILE *fd = NULL; + int devfd; struct vfstab vget, vref; + struct dk_minfo dkminfo; int preencnt = 0; struct devlist *dp, *devs = NULL; int status; + uint_t lbs; (void) setlocale(LC_ALL, ""); #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ @@ -408,6 +411,7 @@ main(int argc, char *argv[]) myname); exit(1); } + while (optind < argc) { /* * If "-F FStype" is specified, use that fs type. @@ -464,6 +468,32 @@ try_again: case FSCKDEV: vref.vfs_fsckdev = argv[optind]; + + /* + * Check the media sector size + */ + if (((devfd = open(vref.vfs_fsckdev, + O_RDWR)) >= 0) && (ioctl(devfd, + DKIOCGMEDIAINFO, &dkminfo) != + -1)) { + lbs = dkminfo.dki_lbsize; + if (lbs != 0 && ISP2(lbs / + DEV_BSIZE) && + lbs != DEV_BSIZE) { + fprintf(stderr, + gettext("The device" + " sector size is" + " not supported by" + " fsck\n")); + (void) close(devfd); + exit(1); + } + } + + if (devfd >= 0) { + (void) close(devfd); + } + if ((ret = mygetvfsany(fd, &vget, &vref)) == -1 || vget.vfs_fstype == NULL) { diff --git a/usr/src/cmd/fs.d/pcfs/mkfs/mkfs.c b/usr/src/cmd/fs.d/pcfs/mkfs/mkfs.c index a811306f74..f335a2eabc 100644 --- a/usr/src/cmd/fs.d/pcfs/mkfs/mkfs.c +++ b/usr/src/cmd/fs.d/pcfs/mkfs/mkfs.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -2190,6 +2190,7 @@ open_and_examine(char *dn, bpb_t *wbpb) char *actualdisk = NULL; char *suffix = NULL; int fd; + struct dk_minfo dkminfo; if (Verbose) (void) printf(gettext("Opening destination device/file.\n")); @@ -2210,6 +2211,21 @@ open_and_examine(char *dn, bpb_t *wbpb) } /* + * Check the media sector size + */ + if (ioctl(fd, DKIOCGMEDIAINFO, &dkminfo) != -1) { + if (dkminfo.dki_lbsize != 0 && + ISP2(dkminfo.dki_lbsize / DEV_BSIZE) && + dkminfo.dki_lbsize != DEV_BSIZE) { + (void) fprintf(stderr, + gettext("The device sector size %u is not " + "supported by pcfs!\n"), dkminfo.dki_lbsize); + (void) close(fd); + exit(1); + } + } + + /* * Find appropriate partition if we were requested to do so. */ if (suffix && !(seek_partn(fd, suffix, wbpb, &ignored))) { @@ -2240,6 +2256,7 @@ open_and_seek(char *dn, bpb_t *wbpb, off64_t *seekto) struct fd_char fdchar; struct dk_geom dg; struct stat di; + struct dk_minfo dkminfo; char *actualdisk = NULL; char *suffix = NULL; int fd; @@ -2308,6 +2325,21 @@ open_and_seek(char *dn, bpb_t *wbpb, off64_t *seekto) } /* + * Check the media sector size + */ + if (ioctl(fd, DKIOCGMEDIAINFO, &dkminfo) != -1) { + if (dkminfo.dki_lbsize != 0 && + ISP2(dkminfo.dki_lbsize / DEV_BSIZE) && + dkminfo.dki_lbsize != DEV_BSIZE) { + (void) fprintf(stderr, + gettext("The device sector size %u is not " + "supported by pcfs!\n"), dkminfo.dki_lbsize); + (void) close(fd); + exit(1); + } + } + + /* * Find appropriate partition if we were requested to do so. */ if (suffix && !(seek_partn(fd, suffix, wbpb, seekto))) { diff --git a/usr/src/cmd/fs.d/udfs/mkfs/mkfs.c b/usr/src/cmd/fs.d/udfs/mkfs/mkfs.c index ee228a3c3a..afbc770565 100644 --- a/usr/src/cmd/fs.d/udfs/mkfs/mkfs.c +++ b/usr/src/cmd/fs.d/udfs/mkfs/mkfs.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -31,8 +31,6 @@ * under license from the Regents of the University of California. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * make file system for udfs (UDF - ISO13346) * @@ -298,7 +296,7 @@ main(int32_t argc, int8_t *argv[]) if ((temp_secsz = get_bsize()) != 0) { sectorsize = temp_secsz; } - + /* Get old file system information */ isfs = readvolseq(); @@ -1337,6 +1335,7 @@ get_bsize() { struct dk_cinfo info; struct fd_char fd_char; + struct dk_minfo dkminfo; if (ioctl(fso, DKIOCINFO, &info) < 0) { perror("mkfs DKIOCINFO "); @@ -1350,6 +1349,18 @@ get_bsize() case DKC_CDROM : return (2048); case DKC_SCSI_CCS : + if (ioctl(fso, DKIOCGMEDIAINFO, &dkminfo) != -1) { + if (dkminfo.dki_lbsize != 0 && + POWEROF2(dkminfo.dki_lbsize / DEV_BSIZE) && + dkminfo.dki_lbsize != DEV_BSIZE) { + fprintf(stderr, + gettext("The device sector size " + "%u is not supported by udfs!\n"), + dkminfo.dki_lbsize); + (void) close(fso); + exit(1); + } + } /* FALLTHROUGH */ case DKC_INTEL82072 : /* FALLTHROUGH */ diff --git a/usr/src/cmd/fs.d/ufs/mkfs/mkfs.c b/usr/src/cmd/fs.d/ufs/mkfs/mkfs.c index de6f6bc3e6..5fe8d43b75 100644 --- a/usr/src/cmd/fs.d/ufs/mkfs/mkfs.c +++ b/usr/src/cmd/fs.d/ufs/mkfs/mkfs.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -632,6 +632,7 @@ main(int argc, char *argv[]) struct statvfs64 fs; struct dk_geom dkg; struct dk_cinfo dkcinfo; + struct dk_minfo dkminfo; char pbuf[sizeof (uint64_t) * 3 + 1]; char *tmpbuf; int width, plen; @@ -1504,6 +1505,21 @@ retry_alternate_logic: } /* + * Check the media sector size + */ + if (ioctl(fso, DKIOCGMEDIAINFO, &dkminfo) != -1) { + if (dkminfo.dki_lbsize != 0 && + POWEROF2(dkminfo.dki_lbsize / DEV_BSIZE) && + dkminfo.dki_lbsize != DEV_BSIZE) { + fprintf(stderr, + gettext("The device sector size %u is not " + "supported by ufs!\n"), dkminfo.dki_lbsize); + (void) close(fso); + exit(1); + } + } + + /* * seed random # generator (for ic_generation) */ #ifdef MKFS_DEBUG diff --git a/usr/src/lib/libefi/common/rdwr_efi.c b/usr/src/lib/libefi/common/rdwr_efi.c index 3a335cfc94..31eb3d3f61 100644 --- a/usr/src/lib/libefi/common/rdwr_efi.c +++ b/usr/src/lib/libefi/common/rdwr_efi.c @@ -185,6 +185,7 @@ efi_alloc_and_init(int fd, uint32_t nparts, struct dk_gpt **vtoc) vptr->efi_last_lba = capacity - 1; vptr->efi_altern_lba = capacity -1; vptr->efi_last_u_lba = vptr->efi_last_lba - nblocks; + (void) uuid_generate((uchar_t *)&uuid); UUID_LE_CONVERT(vptr->efi_disk_uguid, uuid); return (0); @@ -437,7 +438,6 @@ efi_read(int fd, struct dk_gpt *vtoc) vtoc->efi_flags |= EFI_GPT_PRIMARY_CORRUPT; vtoc->efi_nparts = LE_32(efi->efi_gpt_NumberOfPartitionEntries); - /* * Partition tables are between backup GPT header * table and ParitionEntryLBA (the starting LBA of @@ -446,7 +446,9 @@ efi_read(int fd, struct dk_gpt *vtoc) * dk_ioc.dki_data, we try to get GUID partition * entry array here. */ - dk_ioc.dki_data++; + /* LINTED */ + dk_ioc.dki_data = (efi_gpt_t *)((char *)dk_ioc.dki_data + + disk_info.dki_lbsize); if (legacy_label) dk_ioc.dki_length = disk_info.dki_capacity - 1 - dk_ioc.dki_lba; @@ -468,7 +470,9 @@ efi_read(int fd, struct dk_gpt *vtoc) } else if (rval == 0) { dk_ioc.dki_lba = LE_64(efi->efi_gpt_PartitionEntryLBA); - dk_ioc.dki_data++; + /* LINTED */ + dk_ioc.dki_data = (efi_gpt_t *)((char *)dk_ioc.dki_data + + disk_info.dki_lbsize); dk_ioc.dki_length = label_len - disk_info.dki_lbsize; rval = efi_ioctl(fd, DKIOCGETEFI, &dk_ioc); @@ -565,20 +569,32 @@ write_pmbr(int fd, struct dk_gpt *vtoc) struct mboot mb; uchar_t *cp; diskaddr_t size_in_lba; + uchar_t *buf; + int len; + + len = (vtoc->efi_lbasize == 0) ? sizeof (mb) : vtoc->efi_lbasize; + buf = calloc(len, 1); /* * Preserve any boot code and disk signature if the first block is * already an MBR. */ dk_ioc.dki_lba = 0; - dk_ioc.dki_length = sizeof (mb); + dk_ioc.dki_length = len; /* LINTED -- always longlong aligned */ - dk_ioc.dki_data = (efi_gpt_t *)&mb; - if (efi_ioctl(fd, DKIOCGETEFI, &dk_ioc) == -1 || - mb.signature != LE_16(MBB_MAGIC)) { + dk_ioc.dki_data = (efi_gpt_t *)buf; + if (efi_ioctl(fd, DKIOCGETEFI, &dk_ioc) == -1) { + (void *) memcpy(&mb, buf, sizeof (mb)); bzero(&mb, sizeof (mb)); mb.signature = LE_16(MBB_MAGIC); + } else { + (void *) memcpy(&mb, buf, sizeof (mb)); + if (mb.signature != LE_16(MBB_MAGIC)) { + bzero(&mb, sizeof (mb)); + mb.signature = LE_16(MBB_MAGIC); + } } + bzero(&mb.parts, sizeof (mb.parts)); cp = (uchar_t *)&mb.parts[0]; /* bootable or not */ @@ -611,11 +627,14 @@ write_pmbr(int fd, struct dk_gpt *vtoc) *cp++ = 0xff; *cp++ = 0xff; } + + (void *) memcpy(buf, &mb, sizeof (mb)); /* LINTED -- always longlong aligned */ - dk_ioc.dki_data = (efi_gpt_t *)&mb; + dk_ioc.dki_data = (efi_gpt_t *)buf; dk_ioc.dki_lba = 0; - dk_ioc.dki_length = sizeof (mb); + dk_ioc.dki_length = len; if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) { + free(buf); switch (errno) { case EIO: return (VT_EIO); @@ -625,6 +644,7 @@ write_pmbr(int fd, struct dk_gpt *vtoc) return (VT_ERROR); } } + free(buf); return (0); } @@ -873,7 +893,6 @@ efi_write(int fd, struct dk_gpt *vtoc) * for backup GPT header. */ lba_backup_gpt_hdr = vtoc->efi_last_u_lba + 1 + nblocks; - if ((dk_ioc.dki_data = calloc(dk_ioc.dki_length, 1)) == NULL) return (VT_ERROR); @@ -894,7 +913,7 @@ efi_write(int fd, struct dk_gpt *vtoc) UUID_LE_CONVERT(efi->efi_gpt_DiskGUID, vtoc->efi_disk_uguid); /* LINTED -- always longlong aligned */ - efi_parts = (efi_gpe_t *)((char *)dk_ioc.dki_data + sizeof (efi_gpt_t)); + efi_parts = (efi_gpe_t *)((char *)dk_ioc.dki_data + vtoc->efi_lbasize); for (i = 0; i < vtoc->efi_nparts; i++) { for (j = 0; @@ -965,10 +984,14 @@ efi_write(int fd, struct dk_gpt *vtoc) free(dk_ioc.dki_data); return (0); } + /* write backup partition array */ dk_ioc.dki_lba = vtoc->efi_last_u_lba + 1; dk_ioc.dki_length -= vtoc->efi_lbasize; - dk_ioc.dki_data++; + /* LINTED */ + dk_ioc.dki_data = (efi_gpt_t *)((char *)dk_ioc.dki_data + + vtoc->efi_lbasize); + if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) { /* * we wrote the primary label okay, so don't fail @@ -987,7 +1010,9 @@ efi_write(int fd, struct dk_gpt *vtoc) */ dk_ioc.dki_lba = lba_backup_gpt_hdr; dk_ioc.dki_length = vtoc->efi_lbasize; - dk_ioc.dki_data--; + /* LINTED */ + dk_ioc.dki_data = (efi_gpt_t *)((char *)dk_ioc.dki_data - + vtoc->efi_lbasize); efi->efi_gpt_AlternateLBA = LE_64(1ULL); efi->efi_gpt_MyLBA = LE_64(lba_backup_gpt_hdr); efi->efi_gpt_PartitionEntryLBA = LE_64(vtoc->efi_last_u_lba + 1); diff --git a/usr/src/uts/common/io/cmlb.c b/usr/src/uts/common/io/cmlb.c index 75559a9b94..343b1b965c 100644 --- a/usr/src/uts/common/io/cmlb.c +++ b/usr/src/uts/common/io/cmlb.c @@ -1287,6 +1287,9 @@ cmlb_check_update_blockcount(struct cmlb_lun *cl, void *tg_cookie) if ((capacity != 0) && (lbasize != 0)) { cl->cl_blockcount = capacity; cl->cl_tgt_blocksize = lbasize; + if (!cl->cl_is_removable) { + cl->cl_sys_blocksize = lbasize; + } return (0); } else { return (EIO); @@ -1592,7 +1595,7 @@ cmlb_validate_geometry(struct cmlb_lun *cl, boolean_t forcerevalid, int flags, label_addr = (daddr_t)(cl->cl_solaris_offset + DK_LABEL_LOC); - buffer_size = sizeof (struct dk_label); + buffer_size = cl->cl_sys_blocksize; cmlb_dbg(CMLB_TRACE, cl, "cmlb_validate_geometry: " "label_addr: 0x%x allocation size: 0x%x\n", @@ -2199,12 +2202,6 @@ cmlb_use_efi(struct cmlb_lun *cl, diskaddr_t capacity, int flags, ASSERT(mutex_owned(CMLB_MUTEX(cl))); - if (cl->cl_tgt_blocksize != cl->cl_sys_blocksize) { - rval = EINVAL; - goto done_err1; - } - - lbasize = cl->cl_sys_blocksize; cl->cl_reserved = -1; @@ -3637,7 +3634,7 @@ cmlb_dkio_partition(struct cmlb_lun *cl, caddr_t arg, int flag, } buffer = kmem_alloc(EFI_MIN_ARRAY_SIZE, KM_SLEEP); - rval = DK_TG_READ(cl, buffer, 1, DEV_BSIZE, tg_cookie); + rval = DK_TG_READ(cl, buffer, 1, cl->cl_sys_blocksize, tg_cookie); if (rval != 0) goto done_error; @@ -4048,9 +4045,9 @@ cmlb_clear_efi(struct cmlb_lun *cl, void *tg_cookie) cl->cl_reserved = -1; mutex_exit(CMLB_MUTEX(cl)); - gpt = kmem_alloc(sizeof (efi_gpt_t), KM_SLEEP); + gpt = kmem_alloc(cl->cl_sys_blocksize, KM_SLEEP); - if (DK_TG_READ(cl, gpt, 1, DEV_BSIZE, tg_cookie) != 0) { + if (DK_TG_READ(cl, gpt, 1, cl->cl_sys_blocksize, tg_cookie) != 0) { goto done; } @@ -4059,7 +4056,8 @@ cmlb_clear_efi(struct cmlb_lun *cl, void *tg_cookie) if (rval == 0) { /* clear primary */ bzero(gpt, sizeof (efi_gpt_t)); - if (rval = DK_TG_WRITE(cl, gpt, 1, EFI_LABEL_SIZE, tg_cookie)) { + if (rval = DK_TG_WRITE(cl, gpt, 1, cl->cl_sys_blocksize, + tg_cookie)) { cmlb_dbg(CMLB_INFO, cl, "cmlb_clear_efi: clear primary label failed\n"); } @@ -4070,8 +4068,8 @@ cmlb_clear_efi(struct cmlb_lun *cl, void *tg_cookie) goto done; } - if ((rval = DK_TG_READ(cl, gpt, cap - 1, EFI_LABEL_SIZE, tg_cookie)) - != 0) { + if ((rval = DK_TG_READ(cl, gpt, cap - 1, cl->cl_sys_blocksize, + tg_cookie)) != 0) { goto done; } cmlb_swap_efi_gpt(gpt); @@ -4081,7 +4079,7 @@ cmlb_clear_efi(struct cmlb_lun *cl, void *tg_cookie) cmlb_dbg(CMLB_TRACE, cl, "cmlb_clear_efi clear backup@%lu\n", cap - 1); bzero(gpt, sizeof (efi_gpt_t)); - if ((rval = DK_TG_WRITE(cl, gpt, cap - 1, EFI_LABEL_SIZE, + if ((rval = DK_TG_WRITE(cl, gpt, cap - 1, cl->cl_sys_blocksize, tg_cookie))) { cmlb_dbg(CMLB_INFO, cl, "cmlb_clear_efi: clear backup label failed\n"); @@ -4092,7 +4090,7 @@ cmlb_clear_efi(struct cmlb_lun *cl, void *tg_cookie) * header of this file */ if ((rval = DK_TG_READ(cl, gpt, cap - 2, - EFI_LABEL_SIZE, tg_cookie)) != 0) { + cl->cl_sys_blocksize, tg_cookie)) != 0) { goto done; } cmlb_swap_efi_gpt(gpt); @@ -4104,7 +4102,7 @@ cmlb_clear_efi(struct cmlb_lun *cl, void *tg_cookie) cap - 2); bzero(gpt, sizeof (efi_gpt_t)); if ((rval = DK_TG_WRITE(cl, gpt, cap - 2, - EFI_LABEL_SIZE, tg_cookie))) { + cl->cl_sys_blocksize, tg_cookie))) { cmlb_dbg(CMLB_INFO, cl, "cmlb_clear_efi: clear legacy backup label " "failed\n"); @@ -4113,7 +4111,7 @@ cmlb_clear_efi(struct cmlb_lun *cl, void *tg_cookie) } done: - kmem_free(gpt, sizeof (efi_gpt_t)); + kmem_free(gpt, cl->cl_sys_blocksize); } /* @@ -4210,7 +4208,7 @@ cmlb_clear_vtoc(struct cmlb_lun *cl, void *tg_cookie) struct dk_label *dkl; mutex_exit(CMLB_MUTEX(cl)); - dkl = kmem_zalloc(sizeof (struct dk_label), KM_SLEEP); + dkl = kmem_zalloc(cl->cl_sys_blocksize, KM_SLEEP); mutex_enter(CMLB_MUTEX(cl)); /* * cmlb_set_vtoc uses these fields in order to figure out @@ -4223,7 +4221,7 @@ cmlb_clear_vtoc(struct cmlb_lun *cl, void *tg_cookie) dkl->dkl_nsect = cl->cl_g.dkg_nsect; mutex_exit(CMLB_MUTEX(cl)); (void) cmlb_set_vtoc(cl, dkl, tg_cookie); - kmem_free(dkl, sizeof (struct dk_label)); + kmem_free(dkl, cl->cl_sys_blocksize); mutex_enter(CMLB_MUTEX(cl)); } @@ -4258,7 +4256,7 @@ cmlb_write_label(struct cmlb_lun *cl, void *tg_cookie) ASSERT(mutex_owned(CMLB_MUTEX(cl))); mutex_exit(CMLB_MUTEX(cl)); - dkl = kmem_zalloc(sizeof (struct dk_label), KM_SLEEP); + dkl = kmem_zalloc(cl->cl_sys_blocksize, KM_SLEEP); mutex_enter(CMLB_MUTEX(cl)); bcopy(&cl->cl_vtoc, &dkl->dkl_vtoc, sizeof (struct dk_vtoc)); @@ -4303,7 +4301,7 @@ cmlb_write_label(struct cmlb_lun *cl, void *tg_cookie) rval = cmlb_set_vtoc(cl, dkl, tg_cookie); exit: - kmem_free(dkl, sizeof (struct dk_label)); + kmem_free(dkl, cl->cl_sys_blocksize); mutex_enter(CMLB_MUTEX(cl)); return (rval); } @@ -4422,7 +4420,7 @@ cmlb_dkio_get_mboot(struct cmlb_lun *cl, caddr_t arg, int flag, void *tg_cookie) /* * Read the mboot block, located at absolute block 0 on the target. */ - buffer_size = sizeof (struct mboot); + buffer_size = cl->cl_sys_blocksize; cmlb_dbg(CMLB_TRACE, cl, "cmlb_dkio_get_mboot: allocation size: 0x%x\n", buffer_size); @@ -4481,18 +4479,18 @@ cmlb_dkio_set_mboot(struct cmlb_lun *cl, caddr_t arg, int flag, void *tg_cookie) return (EINVAL); } - mboot = kmem_zalloc(sizeof (struct mboot), KM_SLEEP); + mboot = kmem_zalloc(cl->cl_sys_blocksize, KM_SLEEP); if (ddi_copyin((const void *)arg, mboot, - sizeof (struct mboot), flag) != 0) { - kmem_free(mboot, (size_t)(sizeof (struct mboot))); + cl->cl_sys_blocksize, flag) != 0) { + kmem_free(mboot, cl->cl_sys_blocksize); return (EFAULT); } /* Is this really a master boot record? */ magic = LE_16(mboot->signature); if (magic != MBB_MAGIC) { - kmem_free(mboot, (size_t)(sizeof (struct mboot))); + kmem_free(mboot, cl->cl_sys_blocksize); return (EINVAL); } @@ -4508,7 +4506,7 @@ cmlb_dkio_set_mboot(struct cmlb_lun *cl, caddr_t arg, int flag, void *tg_cookie) rval = cmlb_update_fdisk_and_vtoc(cl, tg_cookie); if ((!cl->cl_f_geometry_is_valid) || (rval != 0)) { mutex_exit(CMLB_MUTEX(cl)); - kmem_free(mboot, (size_t)(sizeof (struct mboot))); + kmem_free(mboot, cl->cl_sys_blocksize); return (rval); } } @@ -4529,7 +4527,7 @@ cmlb_dkio_set_mboot(struct cmlb_lun *cl, caddr_t arg, int flag, void *tg_cookie) #endif cl->cl_msglog_flag |= CMLB_ALLOW_2TB_WARN; mutex_exit(CMLB_MUTEX(cl)); - kmem_free(mboot, (size_t)(sizeof (struct mboot))); + kmem_free(mboot, cl->cl_sys_blocksize); return (rval); } @@ -5098,10 +5096,10 @@ fallback: return (ddi_prop_op(dev, dip, prop_op, mod_flags, (diskaddr_t *)&nblocks64, NULL, NULL, NULL, tg_cookie); /* - * Assume partition information is in DEV_BSIZE units, compute + * Assume partition information is in sys_blocksize units, compute * divisor for size(9P) property representation. */ - dblk = lbasize / DEV_BSIZE; + dblk = lbasize / cl->cl_sys_blocksize; /* Now let ddi_prop_op_nblocks_blksize() handle the request. */ return (ddi_prop_op_nblocks_blksize(dev, dip, prop_op, mod_flags, diff --git a/usr/src/uts/common/io/scsi/targets/sd.c b/usr/src/uts/common/io/scsi/targets/sd.c index f2cbc0df37..8cbc1310a3 100644 --- a/usr/src/uts/common/io/scsi/targets/sd.c +++ b/usr/src/uts/common/io/scsi/targets/sd.c @@ -1017,6 +1017,7 @@ static int sd_pm_idletime = 1; #define sd_free_rqs ssd_free_rqs #define sd_dump_memory ssd_dump_memory #define sd_get_media_info ssd_get_media_info +#define sd_get_media_info_ext ssd_get_media_info_ext #define sd_dkio_ctrl_info ssd_dkio_ctrl_info #define sd_nvpair_str_decode ssd_nvpair_str_decode #define sd_strtok_r ssd_strtok_r @@ -1093,6 +1094,7 @@ static int sd_pm_idletime = 1; #define sd_is_lsi ssd_is_lsi #define sd_tg_rdwr ssd_tg_rdwr #define sd_tg_getinfo ssd_tg_getinfo +#define sd_rmw_msg_print_handler ssd_rmw_msg_print_handler #endif /* #if (defined(__fibre)) */ @@ -1463,7 +1465,7 @@ static int sd_send_scsi_DOORLOCK(sd_ssc_t *ssc, int flag, int path_flag); static int sd_send_scsi_READ_CAPACITY(sd_ssc_t *ssc, uint64_t *capp, uint32_t *lbap, int path_flag); static int sd_send_scsi_READ_CAPACITY_16(sd_ssc_t *ssc, uint64_t *capp, - uint32_t *lbap, int path_flag); + uint32_t *lbap, uint32_t *psp, int path_flag); static int sd_send_scsi_START_STOP_UNIT(sd_ssc_t *ssc, int flag, int path_flag); static int sd_send_scsi_INQUIRY(sd_ssc_t *ssc, uchar_t *bufaddr, @@ -1510,6 +1512,7 @@ static void sd_panic_for_res_conflict(struct sd_lun *un); * Disk Ioctl Function Prototypes */ static int sd_get_media_info(dev_t dev, caddr_t arg, int flag); +static int sd_get_media_info_ext(dev_t dev, caddr_t arg, int flag); static int sd_dkio_ctrl_info(dev_t dev, caddr_t arg, int flag); static int sd_dkio_get_temp(dev_t dev, caddr_t arg, int flag); @@ -1610,6 +1613,11 @@ static int sd_tg_rdwr(dev_info_t *devi, uchar_t cmd, void *bufaddr, static int sd_tg_getinfo(dev_info_t *devi, int cmd, void *arg, void *tg_cookie); /* + * For printing RMW warning message timely + */ +static void sd_rmw_msg_print_handler(void *arg); + +/* * Constants for failfast support: * * SD_FAILFAST_INACTIVE: Instance is currently in a normal state, with NO @@ -1781,13 +1789,19 @@ static sd_chain_t sd_iostart_chain[] = { sd_mapblockaddr_iostart, /* Index: 3 */ sd_core_iostart, /* Index: 4 */ - /* Chain for buf IO for removable-media targets (PM enabled) */ + /* + * Chain for buf IO for removable-media or large sector size + * disk drive targets with RMW needed (PM enabled) + */ sd_mapblockaddr_iostart, /* Index: 5 */ sd_mapblocksize_iostart, /* Index: 6 */ sd_pm_iostart, /* Index: 7 */ sd_core_iostart, /* Index: 8 */ - /* Chain for buf IO for removable-media targets (PM disabled) */ + /* + * Chain for buf IO for removable-media or large sector size + * disk drive targets with RMW needed (PM disabled) + */ sd_mapblockaddr_iostart, /* Index: 9 */ sd_mapblocksize_iostart, /* Index: 10 */ sd_core_iostart, /* Index: 11 */ @@ -1817,6 +1831,26 @@ static sd_chain_t sd_iostart_chain[] = { /* Chain for "direct priority" USCSI commands (all targets) */ sd_core_iostart, /* Index: 25 */ + + /* + * Chain for buf IO for large sector size disk drive targets + * with RMW needed with checksumming (PM enabled) + */ + sd_mapblockaddr_iostart, /* Index: 26 */ + sd_mapblocksize_iostart, /* Index: 27 */ + sd_checksum_iostart, /* Index: 28 */ + sd_pm_iostart, /* Index: 29 */ + sd_core_iostart, /* Index: 30 */ + + /* + * Chain for buf IO for large sector size disk drive targets + * with RMW needed with checksumming (PM disabled) + */ + sd_mapblockaddr_iostart, /* Index: 31 */ + sd_mapblocksize_iostart, /* Index: 32 */ + sd_checksum_iostart, /* Index: 33 */ + sd_core_iostart, /* Index: 34 */ + }; /* @@ -1825,7 +1859,9 @@ static sd_chain_t sd_iostart_chain[] = { */ #define SD_CHAIN_DISK_IOSTART 0 #define SD_CHAIN_DISK_IOSTART_NO_PM 3 +#define SD_CHAIN_MSS_DISK_IOSTART 5 #define SD_CHAIN_RMMEDIA_IOSTART 5 +#define SD_CHAIN_MSS_DISK_IOSTART_NO_PM 9 #define SD_CHAIN_RMMEDIA_IOSTART_NO_PM 9 #define SD_CHAIN_CHKSUM_IOSTART 12 #define SD_CHAIN_CHKSUM_IOSTART_NO_PM 16 @@ -1833,6 +1869,8 @@ static sd_chain_t sd_iostart_chain[] = { #define SD_CHAIN_USCSI_CHKSUM_IOSTART 21 #define SD_CHAIN_DIRECT_CMD_IOSTART 24 #define SD_CHAIN_PRIORITY_CMD_IOSTART 25 +#define SD_CHAIN_MSS_CHKSUM_IOSTART 26 +#define SD_CHAIN_MSS_CHKSUM_IOSTART_NO_PM 31 /* @@ -1859,13 +1897,19 @@ static sd_chain_t sd_iodone_chain[] = { sd_buf_iodone, /* Index: 3 */ sd_mapblockaddr_iodone, /* Index: 4 */ - /* Chain for buf IO for removable-media targets (PM enabled) */ + /* + * Chain for buf IO for removable-media or large sector size + * disk drive targets with RMW needed (PM enabled) + */ sd_buf_iodone, /* Index: 5 */ sd_mapblockaddr_iodone, /* Index: 6 */ sd_mapblocksize_iodone, /* Index: 7 */ sd_pm_iodone, /* Index: 8 */ - /* Chain for buf IO for removable-media targets (PM disabled) */ + /* + * Chain for buf IO for removable-media or large sector size + * disk drive targets with RMW needed (PM disabled) + */ sd_buf_iodone, /* Index: 9 */ sd_mapblockaddr_iodone, /* Index: 10 */ sd_mapblocksize_iodone, /* Index: 11 */ @@ -1895,6 +1939,25 @@ static sd_chain_t sd_iodone_chain[] = { /* Chain for "direct priority" USCSI commands (all targets) */ sd_uscsi_iodone, /* Index: 25 */ + + /* + * Chain for buf IO for large sector size disk drive targets + * with checksumming (PM enabled) + */ + sd_buf_iodone, /* Index: 26 */ + sd_mapblockaddr_iodone, /* Index: 27 */ + sd_mapblocksize_iodone, /* Index: 28 */ + sd_checksum_iodone, /* Index: 29 */ + sd_pm_iodone, /* Index: 30 */ + + /* + * Chain for buf IO for large sector size disk drive targets + * with checksumming (PM disabled) + */ + sd_buf_iodone, /* Index: 31 */ + sd_mapblockaddr_iodone, /* Index: 32 */ + sd_mapblocksize_iodone, /* Index: 33 */ + sd_checksum_iodone, /* Index: 34 */ }; @@ -1910,14 +1973,17 @@ static sd_chain_t sd_iodone_chain[] = { #define SD_CHAIN_DISK_IODONE 2 #define SD_CHAIN_DISK_IODONE_NO_PM 4 #define SD_CHAIN_RMMEDIA_IODONE 8 +#define SD_CHAIN_MSS_DISK_IODONE 8 #define SD_CHAIN_RMMEDIA_IODONE_NO_PM 11 +#define SD_CHAIN_MSS_DISK_IODONE_NO_PM 11 #define SD_CHAIN_CHKSUM_IODONE 15 #define SD_CHAIN_CHKSUM_IODONE_NO_PM 18 #define SD_CHAIN_USCSI_CMD_IODONE 20 #define SD_CHAIN_USCSI_CHKSUM_IODONE 22 #define SD_CHAIN_DIRECT_CMD_IODONE 24 #define SD_CHAIN_PRIORITY_CMD_IODONE 25 - +#define SD_CHAIN_MSS_CHKSUM_IODONE 30 +#define SD_CHAIN_MSS_CHKSUM_IODONE_NO_PM 34 @@ -1940,13 +2006,19 @@ static sd_initpkt_t sd_initpkt_map[] = { sd_initpkt_for_buf, /* Index: 3 */ sd_initpkt_for_buf, /* Index: 4 */ - /* Chain for buf IO for removable-media targets (PM enabled) */ + /* + * Chain for buf IO for removable-media or large sector size + * disk drive targets (PM enabled) + */ sd_initpkt_for_buf, /* Index: 5 */ sd_initpkt_for_buf, /* Index: 6 */ sd_initpkt_for_buf, /* Index: 7 */ sd_initpkt_for_buf, /* Index: 8 */ - /* Chain for buf IO for removable-media targets (PM disabled) */ + /* + * Chain for buf IO for removable-media or large sector size + * disk drive targets (PM disabled) + */ sd_initpkt_for_buf, /* Index: 9 */ sd_initpkt_for_buf, /* Index: 10 */ sd_initpkt_for_buf, /* Index: 11 */ @@ -1977,6 +2049,24 @@ static sd_initpkt_t sd_initpkt_map[] = { /* Chain for "direct priority" USCSI commands (all targets) */ sd_initpkt_for_uscsi, /* Index: 25 */ + /* + * Chain for buf IO for large sector size disk drive targets + * with checksumming (PM enabled) + */ + sd_initpkt_for_buf, /* Index: 26 */ + sd_initpkt_for_buf, /* Index: 27 */ + sd_initpkt_for_buf, /* Index: 28 */ + sd_initpkt_for_buf, /* Index: 29 */ + sd_initpkt_for_buf, /* Index: 30 */ + + /* + * Chain for buf IO for large sector size disk drive targets + * with checksumming (PM disabled) + */ + sd_initpkt_for_buf, /* Index: 31 */ + sd_initpkt_for_buf, /* Index: 32 */ + sd_initpkt_for_buf, /* Index: 33 */ + sd_initpkt_for_buf, /* Index: 34 */ }; @@ -1999,13 +2089,19 @@ static sd_destroypkt_t sd_destroypkt_map[] = { sd_destroypkt_for_buf, /* Index: 3 */ sd_destroypkt_for_buf, /* Index: 4 */ - /* Chain for buf IO for removable-media targets (PM enabled) */ + /* + * Chain for buf IO for removable-media or large sector size + * disk drive targets (PM enabled) + */ sd_destroypkt_for_buf, /* Index: 5 */ sd_destroypkt_for_buf, /* Index: 6 */ sd_destroypkt_for_buf, /* Index: 7 */ sd_destroypkt_for_buf, /* Index: 8 */ - /* Chain for buf IO for removable-media targets (PM disabled) */ + /* + * Chain for buf IO for removable-media or large sector size + * disk drive targets (PM disabled) + */ sd_destroypkt_for_buf, /* Index: 9 */ sd_destroypkt_for_buf, /* Index: 10 */ sd_destroypkt_for_buf, /* Index: 11 */ @@ -2036,6 +2132,24 @@ static sd_destroypkt_t sd_destroypkt_map[] = { /* Chain for "direct priority" USCSI commands (all targets) */ sd_destroypkt_for_uscsi, /* Index: 25 */ + /* + * Chain for buf IO for large sector size disk drive targets + * with checksumming (PM disabled) + */ + sd_destroypkt_for_buf, /* Index: 26 */ + sd_destroypkt_for_buf, /* Index: 27 */ + sd_destroypkt_for_buf, /* Index: 28 */ + sd_destroypkt_for_buf, /* Index: 29 */ + sd_destroypkt_for_buf, /* Index: 30 */ + + /* + * Chain for buf IO for large sector size disk drive targets + * with checksumming (PM enabled) + */ + sd_destroypkt_for_buf, /* Index: 31 */ + sd_destroypkt_for_buf, /* Index: 32 */ + sd_destroypkt_for_buf, /* Index: 33 */ + sd_destroypkt_for_buf, /* Index: 34 */ }; @@ -2066,13 +2180,19 @@ static int sd_chain_type_map[] = { SD_CHAIN_BUFIO, /* Index: 3 */ SD_CHAIN_BUFIO, /* Index: 4 */ - /* Chain for buf IO for removable-media targets (PM enabled) */ + /* + * Chain for buf IO for removable-media or large sector size + * disk drive targets (PM enabled) + */ SD_CHAIN_BUFIO, /* Index: 5 */ SD_CHAIN_BUFIO, /* Index: 6 */ SD_CHAIN_BUFIO, /* Index: 7 */ SD_CHAIN_BUFIO, /* Index: 8 */ - /* Chain for buf IO for removable-media targets (PM disabled) */ + /* + * Chain for buf IO for removable-media or large sector size + * disk drive targets (PM disabled) + */ SD_CHAIN_BUFIO, /* Index: 9 */ SD_CHAIN_BUFIO, /* Index: 10 */ SD_CHAIN_BUFIO, /* Index: 11 */ @@ -2095,13 +2215,32 @@ static int sd_chain_type_map[] = { /* Chain for USCSI commands (checksum targets) */ SD_CHAIN_USCSI, /* Index: 21 */ SD_CHAIN_USCSI, /* Index: 22 */ - SD_CHAIN_USCSI, /* Index: 22 */ + SD_CHAIN_USCSI, /* Index: 23 */ /* Chain for "direct" USCSI commands (all targets) */ SD_CHAIN_DIRECT, /* Index: 24 */ /* Chain for "direct priority" USCSI commands (all targets) */ SD_CHAIN_DIRECT_PRIORITY, /* Index: 25 */ + + /* + * Chain for buf IO for large sector size disk drive targets + * with checksumming (PM enabled) + */ + SD_CHAIN_BUFIO, /* Index: 26 */ + SD_CHAIN_BUFIO, /* Index: 27 */ + SD_CHAIN_BUFIO, /* Index: 28 */ + SD_CHAIN_BUFIO, /* Index: 29 */ + SD_CHAIN_BUFIO, /* Index: 30 */ + + /* + * Chain for buf IO for large sector size disk drive targets + * with checksumming (PM disabled) + */ + SD_CHAIN_BUFIO, /* Index: 31 */ + SD_CHAIN_BUFIO, /* Index: 32 */ + SD_CHAIN_BUFIO, /* Index: 33 */ + SD_CHAIN_BUFIO, /* Index: 34 */ }; @@ -2147,6 +2286,9 @@ static struct sd_chain_index sd_chain_index_map[] = { { SD_CHAIN_USCSI_CHKSUM_IOSTART, SD_CHAIN_USCSI_CHKSUM_IODONE }, { SD_CHAIN_DIRECT_CMD_IOSTART, SD_CHAIN_DIRECT_CMD_IODONE }, { SD_CHAIN_PRIORITY_CMD_IOSTART, SD_CHAIN_PRIORITY_CMD_IODONE }, + { SD_CHAIN_MSS_CHKSUM_IOSTART, SD_CHAIN_MSS_CHKSUM_IODONE }, + { SD_CHAIN_MSS_CHKSUM_IOSTART_NO_PM, SD_CHAIN_MSS_CHKSUM_IODONE_NO_PM }, + }; @@ -2158,9 +2300,13 @@ static struct sd_chain_index sd_chain_index_map[] = { #define SD_CHAIN_INFO_DISK 0 #define SD_CHAIN_INFO_DISK_NO_PM 1 #define SD_CHAIN_INFO_RMMEDIA 2 +#define SD_CHAIN_INFO_MSS_DISK 2 #define SD_CHAIN_INFO_RMMEDIA_NO_PM 3 +#define SD_CHAIN_INFO_MSS_DSK_NO_PM 3 #define SD_CHAIN_INFO_CHKSUM 4 #define SD_CHAIN_INFO_CHKSUM_NO_PM 5 +#define SD_CHAIN_INFO_MSS_DISK_CHKSUM 10 +#define SD_CHAIN_INFO_MSS_DISK_CHKSUM_NO_PM 11 /* un->un_uscsi_chain_type must be set to one of these */ #define SD_CHAIN_INFO_USCSI_CMD 6 @@ -3967,6 +4113,16 @@ sd_set_properties(struct sd_lun *un, char *name, char *value) "min throttle set to %d\n", un->un_min_throttle); } + if (strcasecmp(name, "rmw-type") == 0) { + if (ddi_strtol(value, &endptr, 0, &val) == 0) { + un->un_f_rmw_type = val; + } else { + goto value_invalid; + } + SD_INFO(SD_LOG_ATTACH_DETACH, un, "sd_set_properties: " + "RMW type set to %d\n", un->un_f_rmw_type); + } + /* * Validate the throttle values. * If any of the numbers are invalid, set everything to defaults. @@ -4996,7 +5152,10 @@ sd_update_block_info(struct sd_lun *un, uint32_t lbasize, uint64_t capacity) { if (lbasize != 0) { un->un_tgt_blocksize = lbasize; - un->un_f_tgt_blocksize_is_valid = TRUE; + un->un_f_tgt_blocksize_is_valid = TRUE; + if (!un->un_f_has_removable_media) { + un->un_sys_blocksize = lbasize; + } } if (capacity != 0) { @@ -5290,7 +5449,7 @@ sd_get_devid(sd_ssc_t *ssc) /* Calculate the checksum */ chksum = 0; ip = (uint_t *)dkdevid; - for (i = 0; i < ((un->un_sys_blocksize - sizeof (int))/sizeof (int)); + for (i = 0; i < ((DEV_BSIZE - sizeof (int)) / sizeof (int)); i++) { chksum ^= ip[i]; } @@ -5386,6 +5545,7 @@ static int sd_write_deviceid(sd_ssc_t *ssc) { struct dk_devid *dkdevid; + uchar_t *buf; diskaddr_t blk; uint_t *ip, chksum; int status; @@ -5406,7 +5566,8 @@ sd_write_deviceid(sd_ssc_t *ssc) /* Allocate the buffer */ - dkdevid = kmem_zalloc(un->un_sys_blocksize, KM_SLEEP); + buf = kmem_zalloc(un->un_sys_blocksize, KM_SLEEP); + dkdevid = (struct dk_devid *)buf; /* Fill in the revision */ dkdevid->dkd_rev_hi = DK_DEVID_REV_MSB; @@ -5421,7 +5582,7 @@ sd_write_deviceid(sd_ssc_t *ssc) /* Calculate the checksum */ chksum = 0; ip = (uint_t *)dkdevid; - for (i = 0; i < ((un->un_sys_blocksize - sizeof (int))/sizeof (int)); + for (i = 0; i < ((DEV_BSIZE - sizeof (int)) / sizeof (int)); i++) { chksum ^= ip[i]; } @@ -5430,12 +5591,12 @@ sd_write_deviceid(sd_ssc_t *ssc) DKD_FORMCHKSUM(chksum, dkdevid); /* Write the reserved sector */ - status = sd_send_scsi_WRITE(ssc, dkdevid, un->un_sys_blocksize, blk, + status = sd_send_scsi_WRITE(ssc, buf, un->un_sys_blocksize, blk, SD_PATH_DIRECT); if (status != 0) sd_ssc_assessment(ssc, SD_FMT_IGNORE); - kmem_free(dkdevid, un->un_sys_blocksize); + kmem_free(buf, un->un_sys_blocksize); mutex_enter(SD_MUTEX(un)); return (status); @@ -5903,6 +6064,14 @@ sd_ddi_suspend(dev_info_t *devi) mutex_exit(&un->un_pm_mutex); } + if (un->un_rmw_msg_timeid != NULL) { + timeout_id_t temp_id = un->un_rmw_msg_timeid; + un->un_rmw_msg_timeid = NULL; + mutex_exit(SD_MUTEX(un)); + (void) untimeout(temp_id); + mutex_enter(SD_MUTEX(un)); + } + if (un->un_retry_timeid != NULL) { timeout_id_t temp_id = un->un_retry_timeid; un->un_retry_timeid = NULL; @@ -6217,7 +6386,7 @@ sd_pm_idletimeout_handler(void *arg) } else { un->un_buf_chain_type = SD_CHAIN_INFO_DISK; } - un->un_uscsi_chain_type = SD_CHAIN_INFO_USCSI_CMD; + un->un_uscsi_chain_type = SD_CHAIN_INFO_USCSI_CMD; SD_TRACE(SD_LOG_IO_PM, un, "sd_pm_idletimeout_handler: idling device\n"); @@ -6839,6 +7008,7 @@ sd_unit_attach(dev_info_t *devi) struct scsi_device *devp; struct sd_lun *un; char *variantp; + char name_str[48]; int reservation_flag = SD_TARGET_IS_UNRESERVED; int instance; int rval; @@ -7267,6 +7437,7 @@ sd_unit_attach(dev_info_t *devi) * meaning a non-zero value must be entered to change the default. */ un->un_f_disksort_disabled = FALSE; + un->un_f_rmw_type = SD_RMW_TYPE_DEFAULT; /* * Retrieve the properties from the static driver table or the driver @@ -7906,6 +8077,24 @@ sd_unit_attach(dev_info_t *devi) un->un_f_write_cache_enabled = (wc_enabled != 0); mutex_exit(SD_MUTEX(un)); + if (un->un_f_rmw_type != SD_RMW_TYPE_RETURN_ERROR && + un->un_tgt_blocksize != DEV_BSIZE) { + if (!(un->un_wm_cache)) { + (void) snprintf(name_str, sizeof (name_str), + "%s%d_cache", + ddi_driver_name(SD_DEVINFO(un)), + ddi_get_instance(SD_DEVINFO(un))); + un->un_wm_cache = kmem_cache_create( + name_str, sizeof (struct sd_w_map), + 8, sd_wm_cache_constructor, + sd_wm_cache_destructor, NULL, + (void *)un, NULL, 0); + if (!(un->un_wm_cache)) { + goto wm_cache_failed; + } + } + } + /* * Check the value of the NV_SUP bit and set * un_f_suppress_cache_flush accordingly. @@ -7994,7 +8183,7 @@ sd_unit_attach(dev_info_t *devi) /* * An error occurred during the attach; clean up & return failure. */ - +wm_cache_failed: devid_failed: setup_pm_failed: @@ -8057,6 +8246,15 @@ spinup_failed: mutex_enter(SD_MUTEX(un)); } + /* Cancel rmw warning message timeouts */ + if (un->un_rmw_msg_timeid != NULL) { + timeout_id_t temp_id = un->un_rmw_msg_timeid; + un->un_rmw_msg_timeid = NULL; + mutex_exit(SD_MUTEX(un)); + (void) untimeout(temp_id); + mutex_enter(SD_MUTEX(un)); + } + /* Cancel any pending retry timeouts */ if (un->un_retry_timeid != NULL) { timeout_id_t temp_id = un->un_retry_timeid; @@ -8270,6 +8468,14 @@ sd_unit_detach(dev_info_t *devi) mutex_enter(SD_MUTEX(un)); } + if (un->un_rmw_msg_timeid != NULL) { + timeout_id_t temp_id = un->un_rmw_msg_timeid; + un->un_rmw_msg_timeid = NULL; + mutex_exit(SD_MUTEX(un)); + (void) untimeout(temp_id); + mutex_enter(SD_MUTEX(un)); + } + if (un->un_dcvb_timeid != NULL) { timeout_id_t temp_id = un->un_dcvb_timeid; un->un_dcvb_timeid = NULL; @@ -10288,7 +10494,9 @@ sd_ready_and_valid(sd_ssc_t *ssc, int part) * a media is changed this routine will be called and the * block size is a function of media rather than device. */ - if (un->un_f_non_devbsize_supported && NOT_DEVBSIZE(un)) { + if ((un->un_f_rmw_type != SD_RMW_TYPE_RETURN_ERROR || + un->un_f_non_devbsize_supported) && + un->un_tgt_blocksize != DEV_BSIZE) { if (!(un->un_wm_cache)) { (void) snprintf(name_str, sizeof (name_str), "%s%d_cache", @@ -10518,17 +10726,20 @@ sdread(dev_t dev, struct uio *uio, cred_t *cred_p) /* * Read requests are restricted to multiples of the system block size. */ - secmask = un->un_sys_blocksize - 1; + if (un->un_f_rmw_type == SD_RMW_TYPE_RETURN_ERROR) + secmask = un->un_tgt_blocksize - 1; + else + secmask = DEV_BSIZE - 1; if (uio->uio_loffset & ((offset_t)(secmask))) { SD_ERROR(SD_LOG_READ_WRITE, un, "sdread: file offset not modulo %d\n", - un->un_sys_blocksize); + secmask + 1); err = EINVAL; } else if (uio->uio_iov->iov_len & (secmask)) { SD_ERROR(SD_LOG_READ_WRITE, un, "sdread: transfer length not modulo %d\n", - un->un_sys_blocksize); + secmask + 1); err = EINVAL; } else { err = physio(sdstrategy, NULL, dev, B_READ, sdmin, uio); @@ -10604,17 +10815,20 @@ sdwrite(dev_t dev, struct uio *uio, cred_t *cred_p) /* * Write requests are restricted to multiples of the system block size. */ - secmask = un->un_sys_blocksize - 1; + if (un->un_f_rmw_type == SD_RMW_TYPE_RETURN_ERROR) + secmask = un->un_tgt_blocksize - 1; + else + secmask = DEV_BSIZE - 1; if (uio->uio_loffset & ((offset_t)(secmask))) { SD_ERROR(SD_LOG_READ_WRITE, un, "sdwrite: file offset not modulo %d\n", - un->un_sys_blocksize); + secmask + 1); err = EINVAL; } else if (uio->uio_iov->iov_len & (secmask)) { SD_ERROR(SD_LOG_READ_WRITE, un, "sdwrite: transfer length not modulo %d\n", - un->un_sys_blocksize); + secmask + 1); err = EINVAL; } else { err = physio(sdstrategy, NULL, dev, B_WRITE, sdmin, uio); @@ -10690,17 +10904,20 @@ sdaread(dev_t dev, struct aio_req *aio, cred_t *cred_p) /* * Read requests are restricted to multiples of the system block size. */ - secmask = un->un_sys_blocksize - 1; + if (un->un_f_rmw_type == SD_RMW_TYPE_RETURN_ERROR) + secmask = un->un_tgt_blocksize - 1; + else + secmask = DEV_BSIZE - 1; if (uio->uio_loffset & ((offset_t)(secmask))) { SD_ERROR(SD_LOG_READ_WRITE, un, "sdaread: file offset not modulo %d\n", - un->un_sys_blocksize); + secmask + 1); err = EINVAL; } else if (uio->uio_iov->iov_len & (secmask)) { SD_ERROR(SD_LOG_READ_WRITE, un, "sdaread: transfer length not modulo %d\n", - un->un_sys_blocksize); + secmask + 1); err = EINVAL; } else { err = aphysio(sdstrategy, anocancel, dev, B_READ, sdmin, aio); @@ -10776,17 +10993,20 @@ sdawrite(dev_t dev, struct aio_req *aio, cred_t *cred_p) /* * Write requests are restricted to multiples of the system block size. */ - secmask = un->un_sys_blocksize - 1; + if (un->un_f_rmw_type == SD_RMW_TYPE_RETURN_ERROR) + secmask = un->un_tgt_blocksize - 1; + else + secmask = DEV_BSIZE - 1; if (uio->uio_loffset & ((offset_t)(secmask))) { SD_ERROR(SD_LOG_READ_WRITE, un, "sdawrite: file offset not modulo %d\n", - un->un_sys_blocksize); + secmask + 1); err = EINVAL; } else if (uio->uio_iov->iov_len & (secmask)) { SD_ERROR(SD_LOG_READ_WRITE, un, "sdawrite: transfer length not modulo %d\n", - un->un_sys_blocksize); + secmask + 1); err = EINVAL; } else { err = aphysio(sdstrategy, anocancel, dev, B_WRITE, sdmin, aio); @@ -11012,6 +11232,7 @@ sdstrategy(struct buf *bp) biodone(bp); return (0); } + /* As was done in the past, fail new cmds. if state is dumping. */ if (un->un_state == SD_STATE_DUMPING) { bioerror(bp, ENXIO); @@ -11150,6 +11371,27 @@ sd_xbuf_init(struct sd_lun *un, struct buf *bp, struct sd_xbuf *xp, /* FALLTHRU */ case SD_CHAIN_BUFIO: index = un->un_buf_chain_type; + if ((!un->un_f_has_removable_media) && + (un->un_tgt_blocksize != 0) && + (un->un_tgt_blocksize != DEV_BSIZE)) { + int secmask = 0, blknomask = 0; + blknomask = + (un->un_tgt_blocksize / DEV_BSIZE) - 1; + secmask = un->un_tgt_blocksize - 1; + + if ((bp->b_lblkno & (blknomask)) || + (bp->b_bcount & (secmask))) { + if (un->un_f_rmw_type != + SD_RMW_TYPE_RETURN_ERROR) { + if (un->un_f_pm_is_enabled == FALSE) + index = + SD_CHAIN_INFO_MSS_DSK_NO_PM; + else + index = + SD_CHAIN_INFO_MSS_DISK; + } + } + } break; case SD_CHAIN_USCSI: index = un->un_uscsi_chain_type; @@ -12039,6 +12281,20 @@ sd_uscsi_iodone(int index, struct sd_lun *un, struct buf *bp) * request would exceed partition range. Converts * partition-relative block address to absolute. * + * Upon exit of this function: + * 1.I/O is aligned + * xp->xb_blkno represents the absolute sector address + * 2.I/O is misaligned + * xp->xb_blkno represents the absolute logical block address + * based on DEV_BSIZE. The logical block address will be + * converted to physical sector address in sd_mapblocksize_\ + * iostart. + * 3.I/O is misaligned but is aligned in "overrun" buf + * xp->xb_blkno represents the absolute logical block address + * based on DEV_BSIZE. The logical block address will be + * converted to physical sector address in sd_mapblocksize_\ + * iostart. But no RMW will be issued in this case. + * * Context: Can sleep * * Issues: This follows what the old code did, in terms of accessing @@ -12060,6 +12316,8 @@ sd_mapblockaddr_iostart(int index, struct sd_lun *un, struct buf *bp) int partition; diskaddr_t partition_offset; struct sd_xbuf *xp; + int secmask = 0, blknomask = 0; + ushort_t is_aligned = TRUE; ASSERT(un != NULL); ASSERT(bp != NULL); @@ -12116,6 +12374,57 @@ sd_mapblockaddr_iostart(int index, struct sd_lun *un, struct buf *bp) (void) cmlb_partinfo(un->un_cmlbhandle, partition, &nblocks, &partition_offset, NULL, NULL, (void *)SD_PATH_DIRECT); + blknomask = (un->un_tgt_blocksize / DEV_BSIZE) - 1; + secmask = un->un_tgt_blocksize - 1; + + if ((bp->b_lblkno & (blknomask)) || (bp->b_bcount & (secmask))) { + is_aligned = FALSE; + } + + if (!(NOT_DEVBSIZE(un))) { + /* + * If I/O is aligned, no need to involve RMW(Read Modify Write) + * Convert the logical block number to target's physical sector + * number. + */ + if (is_aligned) { + xp->xb_blkno = SD_SYS2TGTBLOCK(un, xp->xb_blkno); + } else { + switch (un->un_f_rmw_type) { + case SD_RMW_TYPE_RETURN_ERROR: + bp->b_flags |= B_ERROR; + goto error_exit; + + case SD_RMW_TYPE_DEFAULT: + mutex_enter(SD_MUTEX(un)); + if (un->un_rmw_msg_timeid == NULL) { + scsi_log(SD_DEVINFO(un), sd_label, + CE_WARN, "I/O request is not " + "aligned with %d disk sector size. " + "It is handled through Read Modify " + "Write but the performance is " + "very low.\n", + un->un_tgt_blocksize); + un->un_rmw_msg_timeid = + timeout(sd_rmw_msg_print_handler, + un, SD_RMW_MSG_PRINT_TIMEOUT); + } else { + un->un_rmw_incre_count ++; + } + mutex_exit(SD_MUTEX(un)); + break; + + case SD_RMW_TYPE_NO_WARNING: + default: + break; + } + + nblocks = SD_TGT2SYSBLOCK(un, nblocks); + partition_offset = SD_TGT2SYSBLOCK(un, + partition_offset); + } + } + /* * blocknum is the starting block number of the request. At this * point it is still relative to the start of the minor device. @@ -12136,7 +12445,7 @@ sd_mapblockaddr_iostart(int index, struct sd_lun *un, struct buf *bp) * a multiple of the system block size. */ if ((blocknum < 0) || (blocknum >= nblocks) || - ((bp->b_bcount & (un->un_sys_blocksize - 1)) != 0)) { + ((bp->b_bcount & (DEV_BSIZE - 1)) != 0)) { bp->b_flags |= B_ERROR; goto error_exit; } @@ -12145,11 +12454,18 @@ sd_mapblockaddr_iostart(int index, struct sd_lun *un, struct buf *bp) * If the requsted # blocks exceeds the available # blocks, that * is an overrun of the partition. */ - requested_nblocks = SD_BYTES2SYSBLOCKS(un, bp->b_bcount); + if ((!NOT_DEVBSIZE(un)) && is_aligned) { + requested_nblocks = SD_BYTES2TGTBLOCKS(un, bp->b_bcount); + } else { + requested_nblocks = SD_BYTES2SYSBLOCKS(bp->b_bcount); + } + available_nblocks = (size_t)(nblocks - blocknum); ASSERT(nblocks >= blocknum); if (requested_nblocks > available_nblocks) { + size_t resid; + /* * Allocate an "overrun" buf to allow the request to proceed * for the amount of space available in the partition. The @@ -12158,8 +12474,14 @@ sd_mapblockaddr_iostart(int index, struct sd_lun *un, struct buf *bp) * replaces the original buf here, and the original buf * is saved inside the overrun buf, for later use. */ - size_t resid = SD_SYSBLOCKS2BYTES(un, - (offset_t)(requested_nblocks - available_nblocks)); + if ((!NOT_DEVBSIZE(un)) && is_aligned) { + resid = SD_TGTBLOCKS2BYTES(un, + (offset_t)(requested_nblocks - available_nblocks)); + } else { + resid = SD_SYSBLOCKS2BYTES( + (offset_t)(requested_nblocks - available_nblocks)); + } + size_t count = bp->b_bcount - resid; /* * Note: count is an unsigned entity thus it'll NEVER @@ -12318,7 +12640,7 @@ sd_mapblocksize_iostart(int index, struct sd_lun *un, struct buf *bp) * un->un_sys_blocksize as its block size or if bcount == 0. * In this case there is no layer-private data block allocated. */ - if ((un->un_tgt_blocksize == un->un_sys_blocksize) || + if ((un->un_tgt_blocksize == DEV_BSIZE) || (bp->b_bcount == 0)) { goto done; } @@ -12333,7 +12655,7 @@ sd_mapblocksize_iostart(int index, struct sd_lun *un, struct buf *bp) SD_INFO(SD_LOG_IO_RMMEDIA, un, "sd_mapblocksize_iostart: " "tgt_blocksize:0x%x sys_blocksize: 0x%x\n", - un->un_tgt_blocksize, un->un_sys_blocksize); + un->un_tgt_blocksize, DEV_BSIZE); SD_INFO(SD_LOG_IO_RMMEDIA, un, "sd_mapblocksize_iostart: " "request start block:0x%x\n", xp->xb_blkno); SD_INFO(SD_LOG_IO_RMMEDIA, un, "sd_mapblocksize_iostart: " @@ -12376,7 +12698,7 @@ sd_mapblocksize_iostart(int index, struct sd_lun *un, struct buf *bp) * Note that end_block is actually the block that follows the last * block of the request, but that's what is needed for the computation. */ - first_byte = SD_SYSBLOCKS2BYTES(un, (offset_t)xp->xb_blkno); + first_byte = SD_SYSBLOCKS2BYTES((offset_t)xp->xb_blkno); start_block = xp->xb_blkno = first_byte / un->un_tgt_blocksize; end_block = (first_byte + bp->b_bcount + un->un_tgt_blocksize - 1) / un->un_tgt_blocksize; @@ -12519,7 +12841,7 @@ sd_mapblocksize_iodone(int index, struct sd_lun *un, struct buf *bp) * There is no shadow buf or layer-private data if the target is * using un->un_sys_blocksize as its block size or if bcount == 0. */ - if ((un->un_tgt_blocksize == un->un_sys_blocksize) || + if ((un->un_tgt_blocksize == DEV_BSIZE) || (bp->b_bcount == 0)) { goto exit; } @@ -15550,6 +15872,48 @@ sd_start_retry_command(void *arg) "sd_start_retry_command: exit\n"); } +/* + * Function: sd_rmw_msg_print_handler + * + * Description: If RMW mode is enabled and warning message is triggered + * print I/O count during a fixed interval. + * + * Arguments: arg - pointer to associated softstate for the device. + * + * Context: timeout(9F) thread context. May not sleep. + */ +static void +sd_rmw_msg_print_handler(void *arg) +{ + struct sd_lun *un = arg; + + ASSERT(un != NULL); + ASSERT(!mutex_owned(SD_MUTEX(un))); + + SD_TRACE(SD_LOG_IO_CORE | SD_LOG_ERROR, un, + "sd_rmw_msg_print_handler: entry\n"); + + mutex_enter(SD_MUTEX(un)); + + if (un->un_rmw_incre_count > 0) { + scsi_log(SD_DEVINFO(un), sd_label, CE_WARN, + "%"PRIu64" I/O requests are not aligned with %d disk " + "sector size in %ld seconds. They are handled through " + "Read Modify Write but the performance is very low!\n", + un->un_rmw_incre_count, un->un_tgt_blocksize, + drv_hztousec(SD_RMW_MSG_PRINT_TIMEOUT) / 1000000); + un->un_rmw_incre_count = 0; + un->un_rmw_msg_timeid = timeout(sd_rmw_msg_print_handler, + un, SD_RMW_MSG_PRINT_TIMEOUT); + } else { + un->un_rmw_msg_timeid = NULL; + } + + mutex_exit(SD_MUTEX(un)); + + SD_TRACE(SD_LOG_IO_CORE | SD_LOG_ERROR, un, + "sd_rmw_msg_print_handler: exit\n"); +} /* * Function: sd_start_direct_priority_command @@ -19336,6 +19700,7 @@ sd_send_scsi_READ_CAPACITY(sd_ssc_t *ssc, uint64_t *capp, uint32_t *lbap, uint32_t *capacity_buf; uint64_t capacity; uint32_t lbasize; + uint32_t pbsize; int status; struct sd_lun *un; @@ -19418,7 +19783,7 @@ sd_send_scsi_READ_CAPACITY(sd_ssc_t *ssc, uint64_t *capp, uint32_t *lbap, if (capacity == 0xffffffff) { sd_ssc_assessment(ssc, SD_FMT_IGNORE); status = sd_send_scsi_READ_CAPACITY_16(ssc, &capacity, - &lbasize, path_flag); + &lbasize, &pbsize, path_flag); if (status != 0) { return (status); } @@ -19467,10 +19832,11 @@ sd_send_scsi_READ_CAPACITY(sd_ssc_t *ssc, uint64_t *capp, uint32_t *lbap, * on the logical unit. The actual logical block count will be * this value plus one. * - * Currently the capacity is saved in terms of un->un_sys_blocksize, - * so scale the capacity value to reflect this. + * Currently, for removable media, the capacity is saved in terms + * of un->un_sys_blocksize, so scale the capacity value to reflect this. */ - capacity = (capacity + 1) * (lbasize / un->un_sys_blocksize); + if (un->un_f_has_removable_media) + capacity = (capacity + 1) * (lbasize / un->un_sys_blocksize); /* * Copy the values from the READ CAPACITY command into the space @@ -19504,15 +19870,19 @@ sd_send_scsi_READ_CAPACITY(sd_ssc_t *ssc, uint64_t *capp, uint32_t *lbap, * determine the device capacity in number of blocks and the * device native block size. If this function returns a failure, * then the values in *capp and *lbap are undefined. - * This routine should always be called by - * sd_send_scsi_READ_CAPACITY which will appy any device - * specific adjustments to capacity and lbasize. + * This routine should be called by sd_send_scsi_READ_CAPACITY + * which will apply any device specific adjustments to capacity + * and lbasize. One exception is it is also called by + * sd_get_media_info_ext. In that function, there is no need to + * adjust the capacity and lbasize. * * Arguments: ssc - ssc contains ptr to soft state struct for the target * capp - ptr to unsigned 64-bit variable to receive the * capacity value from the command. * lbap - ptr to unsigned 32-bit varaible to receive the * block size value from the command + * psp - ptr to unsigned 32-bit variable to receive the + * physical block size value from the command * path_flag - SD_PATH_DIRECT to use the USCSI "direct" chain and * the normal command waitq, or SD_PATH_DIRECT_PRIORITY * to use the USCSI "direct" chain and bypass the normal @@ -19533,7 +19903,7 @@ sd_send_scsi_READ_CAPACITY(sd_ssc_t *ssc, uint64_t *capp, uint32_t *lbap, static int sd_send_scsi_READ_CAPACITY_16(sd_ssc_t *ssc, uint64_t *capp, - uint32_t *lbap, int path_flag) + uint32_t *lbap, uint32_t *psp, int path_flag) { struct scsi_extended_sense sense_buf; struct uscsi_cmd ucmd_buf; @@ -19541,6 +19911,8 @@ sd_send_scsi_READ_CAPACITY_16(sd_ssc_t *ssc, uint64_t *capp, uint64_t *capacity16_buf; uint64_t capacity; uint32_t lbasize; + uint32_t pbsize; + uint32_t lbpb_exp; int status; struct sd_lun *un; @@ -19617,9 +19989,13 @@ sd_send_scsi_READ_CAPACITY_16(sd_ssc_t *ssc, uint64_t *capp, * bytes 8-11: Block length in bytes * (MSB in byte:8 & LSB in byte:11) * + * byte 13: LOGICAL BLOCKS PER PHYSICAL BLOCK EXPONENT */ capacity = BE_64(capacity16_buf[0]); lbasize = BE_32(*(uint32_t *)&capacity16_buf[1]); + lbpb_exp = (BE_64(capacity16_buf[1]) >> 40) & 0x0f; + + pbsize = lbasize << lbpb_exp; /* * Done with capacity16_buf @@ -19666,9 +20042,11 @@ sd_send_scsi_READ_CAPACITY_16(sd_ssc_t *ssc, uint64_t *capp, *capp = capacity; *lbap = lbasize; + *psp = pbsize; SD_TRACE(SD_LOG_IO, un, "sd_send_scsi_READ_CAPACITY_16: " - "capacity:0x%llx lbasize:0x%x\n", capacity, lbasize); + "capacity:0x%llx lbasize:0x%x, pbsize: 0x%x\n", + capacity, lbasize, pbsize); return (0); } @@ -21443,6 +21821,7 @@ sdioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cred_p, int *rval_p) case DKIOCHOTPLUGGABLE: case DKIOCINFO: case DKIOCGMEDIAINFO: + case DKIOCGMEDIAINFOEXT: case MHIOCENFAILFAST: case MHIOCSTATUS: case MHIOCTKOWN: @@ -21509,6 +21888,11 @@ skip_ready_valid: err = sd_get_media_info(dev, (caddr_t)arg, flag); break; + case DKIOCGMEDIAINFOEXT: + SD_TRACE(SD_LOG_IOCTL, un, "DKIOCGMEDIAINFOEXT\n"); + err = sd_get_media_info_ext(dev, (caddr_t)arg, flag); + break; + case DKIOCGGEOM: case DKIOCGVTOC: case DKIOCGEXTVTOC: @@ -22609,6 +22993,205 @@ no_assessment: return (rval); } +/* + * Function: sd_get_media_info_ext + * + * Description: This routine is the driver entry point for handling ioctl + * requests for the media type or command set profile used by the + * drive to operate on the media (DKIOCGMEDIAINFOEXT). The + * difference this ioctl and DKIOCGMEDIAINFO is the return value + * of this ioctl contains both logical block size and physical + * block size. + * + * + * Arguments: dev - the device number + * arg - pointer to user provided dk_minfo_ext structure + * specifying the media type, logical block size, + * physical block size and disk capacity. + * flag - this argument is a pass through to ddi_copyxxx() + * directly from the mode argument of ioctl(). + * + * Return Code: 0 + * EACCESS + * EFAULT + * ENXIO + * EIO + */ + +static int +sd_get_media_info_ext(dev_t dev, caddr_t arg, int flag) +{ + struct sd_lun *un = NULL; + struct uscsi_cmd com; + struct scsi_inquiry *sinq; + struct dk_minfo_ext media_info_ext; + u_longlong_t media_capacity; + uint64_t capacity; + uint_t lbasize; + uint_t pbsize; + uchar_t *out_data; + uchar_t *rqbuf; + int rval = 0; + int rtn; + sd_ssc_t *ssc; + + if ((un = ddi_get_soft_state(sd_state, SDUNIT(dev))) == NULL || + (un->un_state == SD_STATE_OFFLINE)) { + return (ENXIO); + } + + SD_TRACE(SD_LOG_IOCTL_DKIO, un, "sd_get_media_info_ext: entry\n"); + + out_data = kmem_zalloc(SD_PROFILE_HEADER_LEN, KM_SLEEP); + rqbuf = kmem_zalloc(SENSE_LENGTH, KM_SLEEP); + ssc = sd_ssc_init(un); + + /* Issue a TUR to determine if the drive is ready with media present */ + rval = sd_send_scsi_TEST_UNIT_READY(ssc, SD_CHECK_FOR_MEDIA); + if (rval == ENXIO) { + goto done; + } else if (rval != 0) { + sd_ssc_assessment(ssc, SD_FMT_IGNORE); + } + + /* Now get configuration data */ + if (ISCD(un)) { + media_info_ext.dki_media_type = DK_CDROM; + + /* Allow SCMD_GET_CONFIGURATION to MMC devices only */ + if (un->un_f_mmc_cap == TRUE) { + rtn = sd_send_scsi_GET_CONFIGURATION(ssc, &com, rqbuf, + SENSE_LENGTH, out_data, SD_PROFILE_HEADER_LEN, + SD_PATH_STANDARD); + + if (rtn) { + /* + * We ignore all failures for CD and need to + * put the assessment before processing code + * to avoid missing assessment for FMA. + */ + sd_ssc_assessment(ssc, SD_FMT_IGNORE); + /* + * Failed for other than an illegal request + * or command not supported + */ + if ((com.uscsi_status == STATUS_CHECK) && + (com.uscsi_rqstatus == STATUS_GOOD)) { + if ((rqbuf[2] != KEY_ILLEGAL_REQUEST) || + (rqbuf[12] != 0x20)) { + rval = EIO; + goto no_assessment; + } + } + } else { + /* + * The GET CONFIGURATION command succeeded + * so set the media type according to the + * returned data + */ + media_info_ext.dki_media_type = out_data[6]; + media_info_ext.dki_media_type <<= 8; + media_info_ext.dki_media_type |= out_data[7]; + } + } + } else { + /* + * The profile list is not available, so we attempt to identify + * the media type based on the inquiry data + */ + sinq = un->un_sd->sd_inq; + if ((sinq->inq_dtype == DTYPE_DIRECT) || + (sinq->inq_dtype == DTYPE_OPTICAL)) { + /* This is a direct access device or optical disk */ + media_info_ext.dki_media_type = DK_FIXED_DISK; + + if ((bcmp(sinq->inq_vid, "IOMEGA", 6) == 0) || + (bcmp(sinq->inq_vid, "iomega", 6) == 0)) { + if ((bcmp(sinq->inq_pid, "ZIP", 3) == 0)) { + media_info_ext.dki_media_type = DK_ZIP; + } else if ( + (bcmp(sinq->inq_pid, "jaz", 3) == 0)) { + media_info_ext.dki_media_type = DK_JAZ; + } + } + } else { + /* + * Not a CD, direct access or optical disk so return + * unknown media + */ + media_info_ext.dki_media_type = DK_UNKNOWN; + } + } + + /* + * Now read the capacity so we can provide the lbasize, + * pbsize and capacity. + */ + rval = sd_send_scsi_READ_CAPACITY_16(ssc, &capacity, &lbasize, &pbsize, + SD_PATH_DIRECT); + + if (rval != 0) { + rval = sd_send_scsi_READ_CAPACITY(ssc, &capacity, &lbasize, + SD_PATH_DIRECT); + + switch (rval) { + case 0: + pbsize = lbasize; + media_capacity = capacity; + /* + * sd_send_scsi_READ_CAPACITY() reports capacity in + * un->un_sys_blocksize chunks. So we need to convert + * it into cap.lbsize chunks. + */ + if (un->un_f_has_removable_media) { + media_capacity *= un->un_sys_blocksize; + media_capacity /= lbasize; + } + break; + case EACCES: + rval = EACCES; + goto done; + default: + rval = EIO; + goto done; + } + } else { + media_capacity = capacity; + } + + /* + * If lun is expanded dynamically, update the un structure. + */ + mutex_enter(SD_MUTEX(un)); + if ((un->un_f_blockcount_is_valid == TRUE) && + (un->un_f_tgt_blocksize_is_valid == TRUE) && + (capacity > un->un_blockcount)) { + sd_update_block_info(un, lbasize, capacity); + } + mutex_exit(SD_MUTEX(un)); + + media_info_ext.dki_lbsize = lbasize; + media_info_ext.dki_capacity = media_capacity; + media_info_ext.dki_pbsize = pbsize; + + if (ddi_copyout(&media_info_ext, arg, sizeof (struct dk_minfo_ext), + flag)) { + rval = EFAULT; + goto no_assessment; + } +done: + if (rval != 0) { + if (rval == EIO) + sd_ssc_assessment(ssc, SD_FMT_STATUS_CHECK); + else + sd_ssc_assessment(ssc, SD_FMT_IGNORE); + } +no_assessment: + sd_ssc_fini(ssc); + kmem_free(out_data, SD_PROFILE_HEADER_LEN); + kmem_free(rqbuf, SENSE_LENGTH); + return (rval); +} /* * Function: sd_check_media @@ -24700,17 +25283,51 @@ sddump(dev_t dev, caddr_t addr, daddr_t blkno, int nblk) partition = SDPART(dev); SD_INFO(SD_LOG_DUMP, un, "sddump: partition = %d\n", partition); + if (!(NOT_DEVBSIZE(un))) { + int secmask = 0; + int blknomask = 0; + + blknomask = (un->un_tgt_blocksize / DEV_BSIZE) - 1; + secmask = un->un_tgt_blocksize - 1; + + if (blkno & blknomask) { + SD_TRACE(SD_LOG_DUMP, un, + "sddump: dump start block not modulo %d\n", + un->un_tgt_blocksize); + return (EINVAL); + } + + if ((nblk * DEV_BSIZE) & secmask) { + SD_TRACE(SD_LOG_DUMP, un, + "sddump: dump length not modulo %d\n", + un->un_tgt_blocksize); + return (EINVAL); + } + + } + /* Validate blocks to dump at against partition size. */ (void) cmlb_partinfo(un->un_cmlbhandle, partition, &nblks, &start_block, NULL, NULL, (void *)SD_PATH_DIRECT); - if ((blkno + nblk) > nblks) { - SD_TRACE(SD_LOG_DUMP, un, - "sddump: dump range larger than partition: " - "blkno = 0x%x, nblk = 0x%x, dkl_nblk = 0x%x\n", - blkno, nblk, nblks); - return (EINVAL); + if (NOT_DEVBSIZE(un)) { + if ((blkno + nblk) > nblks) { + SD_TRACE(SD_LOG_DUMP, un, + "sddump: dump range larger than partition: " + "blkno = 0x%x, nblk = 0x%x, dkl_nblk = 0x%x\n", + blkno, nblk, nblks); + return (EINVAL); + } + } else { + if (((blkno / (un->un_tgt_blocksize / DEV_BSIZE)) + + (nblk / (un->un_tgt_blocksize / DEV_BSIZE))) > nblks) { + SD_TRACE(SD_LOG_DUMP, un, + "sddump: dump range larger than partition: " + "blkno = 0x%x, nblk = 0x%x, dkl_nblk = 0x%x\n", + blkno, nblk, nblks); + return (EINVAL); + } } mutex_enter(&un->un_pm_mutex); @@ -24813,7 +25430,12 @@ sddump(dev_t dev, caddr_t addr, daddr_t blkno, int nblk) * Convert the partition-relative block number to a * disk physical block number. */ - blkno += start_block; + if (NOT_DEVBSIZE(un)) { + blkno += start_block; + } else { + blkno = blkno / (un->un_tgt_blocksize / DEV_BSIZE); + blkno += start_block; + } SD_INFO(SD_LOG_DUMP, un, "sddump: disk blkno = 0x%x\n", blkno); @@ -24901,6 +25523,10 @@ sddump(dev_t dev, caddr_t addr, daddr_t blkno, int nblk) dma_resid = wr_bp->b_bcount; oblkno = blkno; + if (!(NOT_DEVBSIZE(un))) { + nblk = nblk / (un->un_tgt_blocksize / DEV_BSIZE); + } + while (dma_resid != 0) { for (i = 0; i < SD_NDUMP_RETRIES; i++) { @@ -29894,7 +30520,7 @@ sd_tg_rdwr(dev_info_t *devi, uchar_t cmd, void *bufaddr, * sys_blocksize != tgt_blocksize, need to re-adjust * blkno and save the index to beginning of dk_label */ - first_byte = SD_SYSBLOCKS2BYTES(un, start_block); + first_byte = SD_SYSBLOCKS2BYTES(start_block); real_addr = first_byte / un->un_tgt_blocksize; end_block = (first_byte + reqlength + diff --git a/usr/src/uts/common/os/dumpsubr.c b/usr/src/uts/common/os/dumpsubr.c index 201d6d1bfd..0753cc19da 100644 --- a/usr/src/uts/common/os/dumpsubr.c +++ b/usr/src/uts/common/os/dumpsubr.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -255,12 +255,12 @@ dumpinit(vnode_t *vp, char *name, int justchecking) if (VOP_OPEN(&cdev_vp, FREAD | FWRITE, kcred, NULL) == 0) { size_t blk_size; struct dk_cinfo dki; - struct extvtoc vtoc; + struct dk_minfo minf; - if (VOP_IOCTL(cdev_vp, DKIOCGEXTVTOC, (intptr_t)&vtoc, - FKIOCTL, kcred, NULL, NULL) == 0 && - vtoc.v_sectorsz != 0) - blk_size = vtoc.v_sectorsz; + if (VOP_IOCTL(cdev_vp, DKIOCGMEDIAINFO, + (intptr_t)&minf, FKIOCTL, kcred, NULL, NULL) + == 0 && minf.dki_lbsize != 0) + blk_size = minf.dki_lbsize; else blk_size = DEV_BSIZE; diff --git a/usr/src/uts/common/sys/dkio.h b/usr/src/uts/common/sys/dkio.h index 18f49e513a..caf7d7976d 100644 --- a/usr/src/uts/common/sys/dkio.h +++ b/usr/src/uts/common/sys/dkio.h @@ -20,7 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -301,6 +301,11 @@ enum dkio_state { DKIO_NONE, DKIO_EJECTED, DKIO_INSERTED, DKIO_DEV_GONE }; #define DKIOCGTEMPERATURE (DKIOC|45) /* get temperature */ /* + * ioctl to get the media info including physical block size + */ +#define DKIOCGMEDIAINFOEXT (DKIOC|48) + +/* * Used for providing the temperature. */ @@ -324,6 +329,17 @@ struct dk_minfo { }; /* + * Used for Media info or the current profile info + * including physical block size if supported. + */ +struct dk_minfo_ext { + uint_t dki_media_type; /* Media type or profile info */ + uint_t dki_lbsize; /* Logical blocksize of media */ + diskaddr_t dki_capacity; /* Capacity as # of dki_lbsize blks */ + uint_t dki_pbsize; /* Physical blocksize of media */ +}; + +/* * Media types or profiles known */ #define DK_UNKNOWN 0x00 /* Media inserted - type unknown */ diff --git a/usr/src/uts/common/sys/dklabel.h b/usr/src/uts/common/sys/dklabel.h index 01baa7157c..457c1ecadc 100644 --- a/usr/src/uts/common/sys/dklabel.h +++ b/usr/src/uts/common/sys/dklabel.h @@ -20,7 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -207,7 +207,7 @@ struct dk_label { uint16_t dkl_ncyl; /* # of data cylinders */ uint16_t dkl_acyl; /* # of alternate cylinders */ uint16_t dkl_nhead; /* # of heads in this partition */ - uint16_t dkl_nsect; /* # of 512 byte sectors per track */ + uint16_t dkl_nsect; /* # of sectors per track */ uint16_t dkl_obs3; /* obsolete */ uint16_t dkl_obs4; /* obsolete */ struct dk_map32 dkl_map[NDKMAP]; /* logical partition headers */ diff --git a/usr/src/uts/common/sys/scsi/targets/sddef.h b/usr/src/uts/common/sys/scsi/targets/sddef.h index c5bbc59ef1..90129e40c3 100644 --- a/usr/src/uts/common/sys/scsi/targets/sddef.h +++ b/usr/src/uts/common/sys/scsi/targets/sddef.h @@ -438,7 +438,8 @@ struct sd_lun { /* SYNC CACHE needs to be */ /* sent in sdclose */ un_f_devid_transport_defined :1, /* devid defined by transport */ - un_f_reserved :12; + un_f_rmw_type :2, /* RMW type */ + un_f_reserved :10; /* Ptr to table of strings for ASC/ASCQ error message printing */ struct scsi_asq_key_strings *un_additional_codes; @@ -477,6 +478,8 @@ struct sd_lun { struct kmem_cache *un_wm_cache; /* fast alloc in non-512 write case */ uint_t un_rmw_count; /* count of read-modify-writes */ struct sd_w_map *un_wm; /* head of sd_w_map chain */ + uint64_t un_rmw_incre_count; /* count I/O */ + timeout_id_t un_rmw_msg_timeid; /* for RMW message control */ /* For timeout callback to issue a START STOP UNIT command */ timeout_id_t un_startstop_timeid; @@ -560,12 +563,12 @@ struct sd_lun { (blockcount * (un)->un_tgt_blocksize) /* Convert a byte count to a number of system blocks */ -#define SD_BYTES2SYSBLOCKS(un, bytecount) \ - ((bytecount + (un->un_sys_blocksize - 1))/un->un_sys_blocksize) +#define SD_BYTES2SYSBLOCKS(bytecount) \ + ((bytecount + (DEV_BSIZE - 1))/DEV_BSIZE) /* Convert a system block count to a number of bytes */ -#define SD_SYSBLOCKS2BYTES(un, blockcount) \ - (blockcount * (un)->un_sys_blocksize) +#define SD_SYSBLOCKS2BYTES(blockcount) \ + (blockcount * DEV_BSIZE) /* * Calculate the number of bytes needed to hold the requested number of bytes @@ -579,13 +582,19 @@ struct sd_lun { * to the system block location. */ #define SD_TGTBYTEOFFSET(un, sysblk, tgtblk) \ - (SD_SYSBLOCKS2BYTES(un, sysblk) - SD_TGTBLOCKS2BYTES(un, tgtblk)) + (SD_SYSBLOCKS2BYTES(sysblk) - SD_TGTBLOCKS2BYTES(un, tgtblk)) /* * Calculate the target block location from the system block location */ #define SD_SYS2TGTBLOCK(un, blockcnt) \ - ((blockcnt * un->un_sys_blocksize) / un->un_tgt_blocksize) + (blockcnt / ((un)->un_tgt_blocksize / DEV_BSIZE)) + +/* + * Calculate the target block location from the system block location + */ +#define SD_TGT2SYSBLOCK(un, blockcnt) \ + (blockcnt * ((un)->un_tgt_blocksize / DEV_BSIZE)) /* * SD_DEFAULT_MAX_XFER_SIZE is the default value to bound the max xfer @@ -768,6 +777,12 @@ _NOTE(MUTEX_PROTECTS_DATA(sd_lun::un_fi_mutex, #define SD_WTYPE_RMW 0x002 /* Write requires read-modify-write */ #define SD_WM_BUSY 0x100 /* write-map is busy */ +/* + * RMW type + */ +#define SD_RMW_TYPE_DEFAULT 0 /* do rmw with warning message */ +#define SD_RMW_TYPE_NO_WARNING 1 /* do rmw without warning message */ +#define SD_RMW_TYPE_RETURN_ERROR 2 /* rmw disabled */ /* Device error kstats */ struct sd_errstats { @@ -1678,6 +1693,11 @@ struct sd_fm_internal { #define SD_RESTART_TIMEOUT (drv_usectohz((clock_t)100000)) /* + * 10s misaligned I/O warning message interval + */ +#define SD_RMW_MSG_PRINT_TIMEOUT (drv_usectohz((clock_t)10000000)) + +/* * 100 msec. is what we'll wait for certain retries for fibre channel * targets, 0 msec for parallel SCSI. */ diff --git a/usr/src/uts/common/xen/io/xdb.c b/usr/src/uts/common/xen/io/xdb.c index 16fd5aff9d..06551ebe85 100644 --- a/usr/src/uts/common/xen/io/xdb.c +++ b/usr/src/uts/common/xen/io/xdb.c @@ -1202,6 +1202,7 @@ xdb_open_device(xdb_t *vdp) { dev_info_t *dip = vdp->xs_dip; uint64_t devsize; + int blksize; char *nodepath; ASSERT(MUTEX_HELD(&vdp->xs_cbmutex)); @@ -1252,7 +1253,17 @@ xdb_open_device(xdb_t *vdp) kmem_free(nodepath, MAXPATHLEN); return (DDI_FAILURE); } - vdp->xs_sectors = devsize / XB_BSIZE; + + blksize = ldi_prop_get_int64(vdp->xs_ldi_hdl, + DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, + "blksize", DEV_BSIZE); + if (blksize == DEV_BSIZE) + blksize = ldi_prop_get_int(vdp->xs_ldi_hdl, + LDI_DEV_T_ANY | DDI_PROP_DONTPASS | + DDI_PROP_NOTPROM, "device-blksize", DEV_BSIZE); + + vdp->xs_sec_size = blksize; + vdp->xs_sectors = devsize / blksize; /* check if the underlying device is a CD/DVD disc */ if (ldi_prop_get_int(vdp->xs_ldi_hdl, LDI_DEV_T_ANY | DDI_PROP_DONTPASS, @@ -1388,13 +1399,12 @@ trans_retry: /* If feature-barrier isn't present in xenstore, add it. */ fb_exists = xenbus_exists(xsname, XBP_FB); - /* hard-coded 512-byte sector size */ - ssize = DEV_BSIZE; + ssize = (vdp->xs_sec_size == 0) ? DEV_BSIZE : vdp->xs_sec_size; sectors = vdp->xs_sectors; if (((!fb_exists && (err = xenbus_printf(xbt, xsname, XBP_FB, "%d", 1)))) || (err = xenbus_printf(xbt, xsname, XBP_INFO, "%u", dinfo)) || - (err = xenbus_printf(xbt, xsname, "sector-size", "%u", ssize)) || + (err = xenbus_printf(xbt, xsname, XBP_SECTOR_SIZE, "%u", ssize)) || (err = xenbus_printf(xbt, xsname, XBP_SECTORS, "%"PRIu64, sectors)) || (err = xenbus_printf(xbt, xsname, "instance", "%d", instance)) || diff --git a/usr/src/uts/common/xen/io/xdb.h b/usr/src/uts/common/xen/io/xdb.h index f8046e8219..2173ca6ad9 100644 --- a/usr/src/uts/common/xen/io/xdb.h +++ b/usr/src/uts/common/xen/io/xdb.h @@ -113,6 +113,8 @@ struct xdb { uint32_t xs_type; /* # of total sectors */ uint64_t xs_sectors; + /* sector size if existed */ + uint_t xs_sec_size; /* blkif I/O request ring buffer */ xendev_ring_t *xs_ring; /* handle to access the ring buffer */ diff --git a/usr/src/uts/common/xen/io/xdf.c b/usr/src/uts/common/xen/io/xdf.c index 109421797d..ef50b2bec7 100644 --- a/usr/src/uts/common/xen/io/xdf.c +++ b/usr/src/uts/common/xen/io/xdf.c @@ -478,7 +478,6 @@ vreq_setup(xdf_t *vdp, v_req_t *vreq) if (!ALIGNED_XFER(bp)) { if (bp->b_flags & (B_PAGEIO | B_PHYS)) bp_mapin(bp); - rc = ddi_dma_mem_alloc(vreq->v_memdmahdl, roundup(bp->b_bcount, XB_BSIZE), &xc_acc_attr, DDI_DMA_STREAMING, xdf_dmacallback, (caddr_t)vdp, @@ -1638,11 +1637,13 @@ xdf_get_flush_block(xdf_t *vdp) /* * Get a DEV_BSIZE aligned bufer */ - vdp->xdf_flush_mem = kmem_alloc(DEV_BSIZE * 2, KM_SLEEP); + vdp->xdf_flush_mem = kmem_alloc(vdp->xdf_xdev_secsize * 2, KM_SLEEP); vdp->xdf_cache_flush_block = - (char *)P2ROUNDUP((uintptr_t)(vdp->xdf_flush_mem), DEV_BSIZE); + (char *)P2ROUNDUP((uintptr_t)(vdp->xdf_flush_mem), + (int)vdp->xdf_xdev_secsize); + if (xdf_lb_rdwr(vdp->xdf_dip, TG_READ, vdp->xdf_cache_flush_block, - xdf_flush_block, DEV_BSIZE, NULL) != 0) + xdf_flush_block, vdp->xdf_xdev_secsize, NULL) != 0) return (DDI_FAILURE); return (DDI_SUCCESS); } @@ -1746,7 +1747,7 @@ xdf_synthetic_pgeom(dev_info_t *dip, cmlb_geom_t *geomp) geomp->g_acyl = 0; geomp->g_nhead = XDF_NHEADS; geomp->g_nsect = XDF_NSECTS; - geomp->g_secsize = XB_BSIZE; + geomp->g_secsize = vdp->xdf_xdev_secsize; geomp->g_capacity = vdp->xdf_xdev_nblocks; geomp->g_intrlv = 0; geomp->g_rpm = 7200; @@ -1764,6 +1765,7 @@ xdf_setstate_connected(xdf_t *vdp) dev_info_t *dip = vdp->xdf_dip; cmlb_geom_t pgeom; diskaddr_t nblocks = 0; + uint_t secsize = 0; char *oename, *xsname, *str; uint_t dinfo; @@ -1793,6 +1795,7 @@ xdf_setstate_connected(xdf_t *vdp) */ if (xenbus_gather(XBT_NULL, oename, XBP_SECTORS, "%"SCNu64, &nblocks, + XBP_SECTOR_SIZE, "%u", &secsize, XBP_INFO, "%u", &dinfo, NULL) != 0) { cmn_err(CE_WARN, "xdf@%s: xdf_setstate_connected: " @@ -1808,7 +1811,10 @@ xdf_setstate_connected(xdf_t *vdp) dinfo |= VDISK_CDROM; strfree(str); + if (secsize == 0 || !(ISP2(secsize / DEV_BSIZE))) + secsize = DEV_BSIZE; vdp->xdf_xdev_nblocks = nblocks; + vdp->xdf_xdev_secsize = secsize; #ifdef _ILP32 if (vdp->xdf_xdev_nblocks > DK_MAX_BLOCKS) { cmn_err(CE_WARN, "xdf@%s: xdf_setstate_connected: " @@ -2373,6 +2379,14 @@ xdf_lb_getattribute(dev_info_t *dip, tg_attribute_t *tgattributep) int xdf_lb_getinfo(dev_info_t *dip, int cmd, void *arg, void *tg_cookie) { + int instance; + xdf_t *vdp; + + instance = ddi_get_instance(dip); + + if ((vdp = ddi_get_soft_state(xdf_ssp, instance)) == NULL) + return (ENXIO); + switch (cmd) { case TG_GETPHYGEOM: return (xdf_lb_getpgeom(dip, (cmlb_geom_t *)arg)); @@ -2381,7 +2395,9 @@ xdf_lb_getinfo(dev_info_t *dip, int cmd, void *arg, void *tg_cookie) case TG_GETCAPACITY: return (xdf_lb_getcap(dip, (diskaddr_t *)arg)); case TG_GETBLOCKSIZE: - *(uint32_t *)arg = XB_BSIZE; + mutex_enter(&vdp->xdf_cb_lk); + *(uint32_t *)arg = vdp->xdf_xdev_secsize; + mutex_exit(&vdp->xdf_cb_lk); return (0); case TG_GETATTR: return (xdf_lb_getattribute(dip, (tg_attribute_t *)arg)); @@ -2404,7 +2420,8 @@ xdf_lb_rdwr(dev_info_t *dip, uchar_t cmd, void *bufp, /* We don't allow IO from the oe_change callback thread */ ASSERT(curthread != vdp->xdf_oe_change_thread); - if ((start + (reqlen >> DEV_BSHIFT)) > vdp->xdf_pgeom.g_capacity) + if ((start + ((reqlen / (vdp->xdf_xdev_secsize / DEV_BSIZE)) + >> DEV_BSHIFT)) > vdp->xdf_pgeom.g_capacity) return (EINVAL); bp = getrbuf(KM_SLEEP); @@ -2412,9 +2429,10 @@ xdf_lb_rdwr(dev_info_t *dip, uchar_t cmd, void *bufp, bp->b_flags = B_BUSY | B_READ; else bp->b_flags = B_BUSY | B_WRITE; + bp->b_un.b_addr = bufp; bp->b_bcount = reqlen; - bp->b_blkno = start; + bp->b_blkno = start * (vdp->xdf_xdev_secsize / DEV_BSIZE); bp->b_edev = DDI_DEV_T_NONE; /* don't have dev_t */ mutex_enter(&vdp->xdf_dev_lk); @@ -2582,7 +2600,7 @@ xdf_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, case DKIOCGMEDIAINFO: { struct dk_minfo media_info; - media_info.dki_lbsize = DEV_BSIZE; + media_info.dki_lbsize = vdp->xdf_xdev_secsize; media_info.dki_capacity = vdp->xdf_pgeom.g_capacity; if (XD_IS_CD(vdp)) media_info.dki_media_type = DK_CDROM; @@ -2664,7 +2682,7 @@ xdf_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, !xdf_barrier_flush_disable) { rv = xdf_lb_rdwr(vdp->xdf_dip, TG_WRITE, vdp->xdf_cache_flush_block, xdf_flush_block, - DEV_BSIZE, (void *)dev); + vdp->xdf_xdev_secsize, (void *)dev); } else { return (ENOTTY); } @@ -2686,6 +2704,7 @@ xdf_strategy(struct buf *bp) xdf_t *vdp; minor_t minor; diskaddr_t p_blkct, p_blkst; + daddr_t blkno; ulong_t nblks; int part; @@ -2726,16 +2745,24 @@ xdf_strategy(struct buf *bp) mutex_enter(&vdp->xdf_dev_lk); } + /* + * Adjust the real blkno and bcount according to the underline + * physical sector size. + */ + blkno = bp->b_blkno / (vdp->xdf_xdev_secsize / XB_BSIZE); + /* check for a starting block beyond the disk or partition limit */ - if (bp->b_blkno > p_blkct) { + if (blkno > p_blkct) { DPRINTF(IO_DBG, ("xdf@%s: block %lld exceeds VBD size %"PRIu64, - vdp->xdf_addr, (longlong_t)bp->b_blkno, (uint64_t)p_blkct)); + vdp->xdf_addr, (longlong_t)blkno, (uint64_t)p_blkct)); + mutex_exit(&vdp->xdf_dev_lk); xdf_io_err(bp, EINVAL, 0); return (0); } /* Legacy: don't set error flag at this case */ - if (bp->b_blkno == p_blkct) { + if (blkno == p_blkct) { + mutex_exit(&vdp->xdf_dev_lk); bp->b_resid = bp->b_bcount; biodone(bp); return (0); @@ -2747,14 +2774,29 @@ xdf_strategy(struct buf *bp) bp->av_back = bp->av_forw = NULL; /* Adjust for partial transfer, this will result in an error later */ - nblks = bp->b_bcount >> XB_BSHIFT; - if ((bp->b_blkno + nblks) > p_blkct) { - bp->b_resid = ((bp->b_blkno + nblks) - p_blkct) << XB_BSHIFT; + if (vdp->xdf_xdev_secsize != 0 && + vdp->xdf_xdev_secsize != XB_BSIZE) { + nblks = bp->b_bcount / vdp->xdf_xdev_secsize; + } else { + nblks = bp->b_bcount >> XB_BSHIFT; + } + + if ((blkno + nblks) > p_blkct) { + if (vdp->xdf_xdev_secsize != 0 && + vdp->xdf_xdev_secsize != XB_BSIZE) { + bp->b_resid = + ((blkno + nblks) - p_blkct) * + vdp->xdf_xdev_secsize; + } else { + bp->b_resid = + ((blkno + nblks) - p_blkct) << + XB_BSHIFT; + } bp->b_bcount -= bp->b_resid; } DPRINTF(IO_DBG, ("xdf@%s: strategy blk %lld len %lu\n", - vdp->xdf_addr, (longlong_t)bp->b_blkno, (ulong_t)bp->b_bcount)); + vdp->xdf_addr, (longlong_t)blkno, (ulong_t)bp->b_bcount)); /* Fix up the buf struct */ bp->b_flags |= B_BUSY; @@ -2792,6 +2834,9 @@ xdf_read(dev_t dev, struct uio *uiop, cred_t *credp) NULL, NULL, NULL, NULL)) return (ENXIO); + if (uiop->uio_loffset >= XB_DTOB(p_blkcnt, vdp)) + return (ENOSPC); + if (U_INVAL(uiop)) return (EINVAL); @@ -2822,7 +2867,7 @@ xdf_write(dev_t dev, struct uio *uiop, cred_t *credp) NULL, NULL, NULL, NULL)) return (ENXIO); - if (uiop->uio_loffset >= XB_DTOB(p_blkcnt)) + if (uiop->uio_loffset >= XB_DTOB(p_blkcnt, vdp)) return (ENOSPC); if (U_INVAL(uiop)) @@ -2853,7 +2898,7 @@ xdf_aread(dev_t dev, struct aio_req *aiop, cred_t *credp) NULL, NULL, NULL, NULL)) return (ENXIO); - if (uiop->uio_loffset >= XB_DTOB(p_blkcnt)) + if (uiop->uio_loffset >= XB_DTOB(p_blkcnt, vdp)) return (ENOSPC); if (U_INVAL(uiop)) @@ -2884,7 +2929,7 @@ xdf_awrite(dev_t dev, struct aio_req *aiop, cred_t *credp) NULL, NULL, NULL, NULL)) return (ENXIO); - if (uiop->uio_loffset >= XB_DTOB(p_blkcnt)) + if (uiop->uio_loffset >= XB_DTOB(p_blkcnt, vdp)) return (ENOSPC); if (U_INVAL(uiop)) @@ -2921,9 +2966,11 @@ xdf_dump(dev_t dev, caddr_t addr, daddr_t blkno, int nblk) NULL, NULL, NULL)) return (ENXIO); - if ((blkno + nblk) > p_blkcnt) { + if ((blkno + nblk) > + (p_blkcnt * (vdp->xdf_xdev_secsize / XB_BSIZE))) { cmn_err(CE_WARN, "xdf@%s: block %ld exceeds VBD size %"PRIu64, - vdp->xdf_addr, blkno + nblk, (uint64_t)p_blkcnt); + vdp->xdf_addr, (daddr_t)((blkno + nblk) / + (vdp->xdf_xdev_secsize / XB_BSIZE)), (uint64_t)p_blkcnt); return (EINVAL); } @@ -3451,7 +3498,7 @@ xdf_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) mutex_destroy(&vdp->xdf_cb_lk); mutex_destroy(&vdp->xdf_dev_lk); if (vdp->xdf_cache_flush_block != NULL) - kmem_free(vdp->xdf_flush_mem, 2 * DEV_BSIZE); + kmem_free(vdp->xdf_flush_mem, 2 * vdp->xdf_xdev_secsize); ddi_soft_state_free(xdf_ssp, instance); return (DDI_SUCCESS); } diff --git a/usr/src/uts/common/xen/io/xdf.h b/usr/src/uts/common/xen/io/xdf.h index a3319f70a3..f2a2a82dd5 100644 --- a/usr/src/uts/common/xen/io/xdf.h +++ b/usr/src/uts/common/xen/io/xdf.h @@ -48,7 +48,7 @@ extern "C" { #define XB_BSIZE DEV_BSIZE #define XB_BMASK (XB_BSIZE - 1) #define XB_BSHIFT 9 -#define XB_DTOB(bn) ((bn) << XB_BSHIFT) +#define XB_DTOB(bn, vdp) ((bn) * (vdp)->xdf_xdev_secsize) #define XB_MAX_SEGLEN (8 * XB_BSIZE) #define XB_SEGOFFSET (XB_MAX_SEGLEN - 1) @@ -222,6 +222,7 @@ typedef struct xdf { kcondvar_t xdf_dev_cv; /* cv used in I/O path */ uint_t xdf_dinfo; /* disk info from backend xenstore */ diskaddr_t xdf_xdev_nblocks; /* total size in block */ + uint_t xdf_xdev_secsize; /* disk blksize from backend */ cmlb_geom_t xdf_pgeom; boolean_t xdf_pgeom_set; boolean_t xdf_pgeom_fixed; diff --git a/usr/src/uts/common/xen/sys/xendev.h b/usr/src/uts/common/xen/sys/xendev.h index 8e5921dc3f..dad4ad222f 100644 --- a/usr/src/uts/common/xen/sys/xendev.h +++ b/usr/src/uts/common/xen/sys/xendev.h @@ -52,6 +52,7 @@ extern "C" { /* * Xenbus property interfaces, initialized by backend disk driver */ +#define XBP_SECTOR_SIZE "sector-size" /* backend prop: uint */ #define XBP_SECTORS "sectors" /* backend prop: uint64 */ #define XBP_INFO "info" /* backend prop: uint */ #define XBP_FB "feature-barrier" /* backend prop: boolean int */ diff --git a/usr/src/uts/sun4v/io/vdc.c b/usr/src/uts/sun4v/io/vdc.c index 6c5d37b940..b7729adeed 100644 --- a/usr/src/uts/sun4v/io/vdc.c +++ b/usr/src/uts/sun4v/io/vdc.c @@ -150,6 +150,7 @@ static void vdc_store_label_vtoc(vdc_t *, struct dk_geom *, static void vdc_store_label_unk(vdc_t *vdc); static boolean_t vdc_is_opened(vdc_t *vdc); static void vdc_update_size(vdc_t *vdc, size_t, size_t, size_t); +static int vdc_update_vio_bsize(vdc_t *vdc, uint32_t); /* handshake with vds */ static int vdc_init_ver_negotiation(vdc_t *vdc, vio_ver_t ver); @@ -621,8 +622,10 @@ vdc_do_attach(dev_info_t *dip) vdc->state = VDC_STATE_INIT; vdc->lifecycle = VDC_LC_ATTACHING; vdc->session_id = 0; - vdc->block_size = DEV_BSIZE; - vdc->max_xfer_sz = maxphys / DEV_BSIZE; + vdc->vdisk_bsize = DEV_BSIZE; + vdc->vio_bmask = 0; + vdc->vio_bshift = 0; + vdc->max_xfer_sz = maxphys / vdc->vdisk_bsize; /* * We assume, for now, that the vDisk server will export 'read' @@ -943,7 +946,7 @@ vdc_set_err_kstats(vdc_t *vdc) stp = (vd_err_stats_t *)vdc->err_stats->ks_data; ASSERT(stp != NULL); - stp->vd_capacity.value.ui64 = vdc->vdisk_size * vdc->block_size; + stp->vd_capacity.value.ui64 = vdc->vdisk_size * vdc->vdisk_bsize; (void) strcpy(stp->vd_vid.value.c, "SUN"); (void) strcpy(stp->vd_pid.value.c, "VDSK"); @@ -1124,7 +1127,7 @@ vdc_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags, name, valuep, lengthp)); } nblocks = vdc->slice[VDCPART(dev)].nblocks; - blksize = vdc->block_size; + blksize = vdc->vdisk_bsize; mutex_exit(&vdc->lock); return (ddi_prop_op_nblocks_blksize(dev, dip, prop_op, mod_flags, @@ -1382,6 +1385,7 @@ vdc_dump(dev_t dev, caddr_t addr, daddr_t blkno, int nblk) size_t nbytes = nblk * DEV_BSIZE; int instance = VDCUNIT(dev); vdc_t *vdc = NULL; + diskaddr_t vio_blkno; if ((vdc = ddi_get_soft_state(vdc_state, instance)) == NULL) { cmn_err(CE_NOTE, "[%d] Couldn't get state structure", instance); @@ -1390,8 +1394,16 @@ vdc_dump(dev_t dev, caddr_t addr, daddr_t blkno, int nblk) DMSG(vdc, 2, "[%d] dump %ld bytes at block 0x%lx : addr=0x%p\n", instance, nbytes, blkno, (void *)addr); + + /* convert logical block to vio block */ + if ((blkno & vdc->vio_bmask) != 0) { + DMSG(vdc, 0, "Misaligned block number (%lu)\n", blkno); + return (EINVAL); + } + vio_blkno = blkno >> vdc->vio_bshift; + rv = vdc_send_request(vdc, VD_OP_BWRITE, addr, nbytes, - VDCPART(dev), blkno, CB_STRATEGY, 0, VIO_write_dir); + VDCPART(dev), vio_blkno, CB_STRATEGY, 0, VIO_write_dir); if (rv) { DMSG(vdc, 0, "Failed to do a disk dump (err=%d)\n", rv); return (rv); @@ -1422,6 +1434,7 @@ vdc_dump(dev_t dev, caddr_t addr, daddr_t blkno, int nblk) static int vdc_strategy(struct buf *buf) { + diskaddr_t vio_blkno; int rv = -1; vdc_t *vdc = NULL; int instance = VDCUNIT(buf->b_edev); @@ -1448,8 +1461,21 @@ vdc_strategy(struct buf *buf) slice = VDCPART(buf->b_edev); } + /* + * In the buf structure, b_lblkno represents a logical block number + * using a block size of 512 bytes. For the VIO request, this block + * number has to be converted to be represented with the block size + * used by the VIO protocol. + */ + if ((buf->b_lblkno & vdc->vio_bmask) != 0) { + bioerror(buf, EINVAL); + biodone(buf); + return (0); + } + vio_blkno = buf->b_lblkno >> vdc->vio_bshift; + rv = vdc_send_request(vdc, op, (caddr_t)buf->b_un.b_addr, - buf->b_bcount, slice, buf->b_lblkno, + buf->b_bcount, slice, vio_blkno, CB_STRATEGY, buf, (op == VD_OP_BREAD) ? VIO_read_dir : VIO_write_dir); @@ -1494,8 +1520,8 @@ vdc_min(struct buf *bufp) vdc = ddi_get_soft_state(vdc_state, instance); VERIFY(vdc != NULL); - if (bufp->b_bcount > (vdc->max_xfer_sz * vdc->block_size)) { - bufp->b_bcount = vdc->max_xfer_sz * vdc->block_size; + if (bufp->b_bcount > (vdc->max_xfer_sz * vdc->vdisk_bsize)) { + bufp->b_bcount = vdc->max_xfer_sz * vdc->vdisk_bsize; } } @@ -1670,7 +1696,7 @@ vdc_init_attr_negotiation(vdc_t *vdc) pkt.tag.vio_sid = vdc->session_id; /* fill in payload */ pkt.max_xfer_sz = vdc->max_xfer_sz; - pkt.vdisk_block_size = vdc->block_size; + pkt.vdisk_block_size = vdc->vdisk_bsize; pkt.xfer_mode = VIO_DRING_MODE_V1_0; pkt.operations = 0; /* server will set bits of valid operations */ pkt.vdisk_type = 0; /* server will set to valid device type */ @@ -2605,13 +2631,13 @@ vdc_init_descriptor_ring(vdc_t *vdc) * as we do not have the capability to split requests over * multiple DRing entries. */ - if ((vdc->max_xfer_sz * vdc->block_size) < maxphys) { + if ((vdc->max_xfer_sz * vdc->vdisk_bsize) < maxphys) { DMSG(vdc, 0, "[%d] using minimum DRing size\n", vdc->instance); vdc->dring_max_cookies = maxphys / PAGESIZE; } else { vdc->dring_max_cookies = - (vdc->max_xfer_sz * vdc->block_size) / PAGESIZE; + (vdc->max_xfer_sz * vdc->vdisk_bsize) / PAGESIZE; } vdc->dring_entry_size = (sizeof (vd_dring_entry_t) + (sizeof (ldc_mem_cookie_t) * @@ -4864,6 +4890,17 @@ vdc_handle_attr_msg(vdc_t *vdc, vd_attr_msg_t *attr_msg) vdc->instance); attr_msg->vdisk_size = 0; } + + /* update the VIO block size */ + if (attr_msg->vdisk_block_size > 0 && + vdc_update_vio_bsize(vdc, + attr_msg->vdisk_block_size) != 0) { + DMSG(vdc, 0, "[%d] Invalid block size (%u) from vds", + vdc->instance, attr_msg->vdisk_block_size); + status = EINVAL; + break; + } + /* update disk, block and transfer sizes */ vdc_update_size(vdc, attr_msg->vdisk_size, attr_msg->vdisk_block_size, attr_msg->max_xfer_sz); @@ -4877,7 +4914,7 @@ vdc_handle_attr_msg(vdc_t *vdc, vd_attr_msg_t *attr_msg) DMSG(vdc, 0, "[%d] max_xfer_sz: sent %lx acked %lx\n", vdc->instance, vdc->max_xfer_sz, attr_msg->max_xfer_sz); DMSG(vdc, 0, "[%d] vdisk_block_size: sent %lx acked %x\n", - vdc->instance, vdc->block_size, + vdc->instance, vdc->vdisk_bsize, attr_msg->vdisk_block_size); if ((attr_msg->xfer_mode != VIO_DRING_MODE_V1_0) || @@ -5266,7 +5303,7 @@ vdc_dkio_partition(vdc_t *vdc, caddr_t arg, int flag) return (EFAULT); } - VD_EFI_DEV_SET(edev, vdc, vd_process_efi_ioctl); + VDC_EFI_DEV_SET(edev, vdc, vd_process_efi_ioctl); if ((rv = vd_efi_alloc_and_read(&edev, &gpt, &gpe)) != 0) { return (rv); @@ -5307,7 +5344,7 @@ vdc_dkio_partition(vdc_t *vdc, caddr_t arg, int flag) * flag - ioctl flags */ static int -vdc_dioctl_rwcmd(dev_t dev, caddr_t arg, int flag) +vdc_dioctl_rwcmd(vdc_t *vdc, caddr_t arg, int flag) { struct dadkio_rwcmd32 rwcmd32; struct dadkio_rwcmd rwcmd; @@ -5351,7 +5388,7 @@ vdc_dioctl_rwcmd(dev_t dev, caddr_t arg, int flag) bzero((caddr_t)&auio, sizeof (struct uio)); auio.uio_iov = &aiov; auio.uio_iovcnt = 1; - auio.uio_loffset = rwcmd.blkaddr * DEV_BSIZE; + auio.uio_loffset = rwcmd.blkaddr * vdc->vdisk_bsize; auio.uio_resid = rwcmd.buflen; auio.uio_segflg = flag & FKIOCTL ? UIO_SYSSPACE : UIO_USERSPACE; @@ -5363,7 +5400,8 @@ vdc_dioctl_rwcmd(dev_t dev, caddr_t arg, int flag) */ buf->b_private = (void *)VD_SLICE_NONE; - status = physio(vdc_strategy, buf, dev, rw, vdc_min, &auio); + status = physio(vdc_strategy, buf, VD_MAKE_DEV(vdc->instance, 0), + rw, vdc_min, &auio); biofini(buf); kmem_free(buf, sizeof (buf_t)); @@ -6639,14 +6677,23 @@ vdc_check_capacity(vdc_t *vdc) if ((rv = vdc_get_capacity(vdc, &dsk_size, &blk_size)) != 0) return (rv); - if (dsk_size == VD_SIZE_UNKNOWN || dsk_size == 0) + if (dsk_size == VD_SIZE_UNKNOWN || dsk_size == 0 || blk_size == 0) return (EINVAL); mutex_enter(&vdc->lock); - vdc_update_size(vdc, dsk_size, blk_size, vdc->max_xfer_sz); + /* + * First try to update the VIO block size (which is the same as the + * vdisk block size). If this returns an error then that means that + * we can not use that block size so basically the vdisk is unusable + * and we return an error. + */ + rv = vdc_update_vio_bsize(vdc, blk_size); + if (rv == 0) + vdc_update_size(vdc, dsk_size, blk_size, vdc->max_xfer_sz); + mutex_exit(&vdc->lock); - return (0); + return (rv); } /* @@ -6969,7 +7016,7 @@ vd_process_ioctl(dev_t dev, int cmd, caddr_t arg, int mode, int *rvalp) case DIOCTL_RWCMD: { - return (vdc_dioctl_rwcmd(dev, arg, mode)); + return (vdc_dioctl_rwcmd(vdc, arg, mode)); } case DKIOCGAPART: @@ -7604,7 +7651,7 @@ vdc_create_fake_geometry(vdc_t *vdc) (void) strcpy(vdc->cinfo->dki_cname, VDC_DRIVER_NAME); (void) strcpy(vdc->cinfo->dki_dname, VDC_DRIVER_NAME); - /* max_xfer_sz is #blocks so we don't need to divide by DEV_BSIZE */ + /* max_xfer_sz is #blocks so we don't need to divide by vdisk_bsize */ vdc->cinfo->dki_maxtransfer = vdc->max_xfer_sz; /* @@ -7660,7 +7707,7 @@ vdc_create_fake_geometry(vdc_t *vdc) } vdc->minfo->dki_capacity = vdc->vdisk_size; - vdc->minfo->dki_lbsize = vdc->block_size; + vdc->minfo->dki_lbsize = vdc->vdisk_bsize; } static ushort_t @@ -7692,7 +7739,7 @@ vdc_update_size(vdc_t *vdc, size_t dsk_size, size_t blk_size, size_t xfr_size) * update anything. */ if (dsk_size == VD_SIZE_UNKNOWN || dsk_size == 0 || - (blk_size == vdc->block_size && dsk_size == vdc->vdisk_size && + (blk_size == vdc->vdisk_bsize && dsk_size == vdc->vdisk_size && xfr_size == vdc->max_xfer_sz)) return; @@ -7706,13 +7753,11 @@ vdc_update_size(vdc_t *vdc, size_t dsk_size, size_t blk_size, size_t xfr_size) if ((xfr_size * blk_size) > (PAGESIZE * DEV_BSIZE)) { DMSG(vdc, 0, "[%d] vds block transfer size too big;" " using max supported by vdc", vdc->instance); - xfr_size = maxphys / DEV_BSIZE; - dsk_size = (dsk_size * blk_size) / DEV_BSIZE; - blk_size = DEV_BSIZE; + xfr_size = maxphys / blk_size; } vdc->max_xfer_sz = xfr_size; - vdc->block_size = blk_size; + vdc->vdisk_bsize = blk_size; vdc->vdisk_size = dsk_size; stp = (vd_err_stats_t *)vdc->err_stats->ks_data; @@ -7723,6 +7768,50 @@ vdc_update_size(vdc_t *vdc, size_t dsk_size, size_t blk_size, size_t xfr_size) } /* + * Update information about the VIO block size. The VIO block size is the + * same as the vdisk block size which is stored in vdc->vdisk_bsize so we + * do not store that information again. + * + * However, buf structures will always use a logical block size of 512 bytes + * (DEV_BSIZE) and we will need to convert logical block numbers to VIO block + * numbers for each read or write operation using vdc_strategy(). To speed up + * this conversion, we expect the VIO block size to be a power of 2 and a + * multiple 512 bytes (DEV_BSIZE), and we cache some useful information. + * + * The function return EINVAL if the new VIO block size (blk_size) is not a + * power of 2 or not a multiple of 512 bytes, otherwise it returns 0. + */ +static int +vdc_update_vio_bsize(vdc_t *vdc, uint32_t blk_size) +{ + uint32_t ratio, n; + int nshift = 0; + + vdc->vio_bmask = 0; + vdc->vio_bshift = 0; + + ASSERT(blk_size > 0); + + if ((blk_size % DEV_BSIZE) != 0) + return (EINVAL); + + ratio = blk_size / DEV_BSIZE; + + for (n = ratio; n > 1; n >>= 1) { + if ((n & 0x1) != 0) { + /* blk_size is not a power of 2 */ + return (EINVAL); + } + nshift++; + } + + vdc->vio_bshift = nshift; + vdc->vio_bmask = ratio - 1; + + return (0); +} + +/* * Function: * vdc_validate_geometry * @@ -7747,7 +7836,7 @@ vdc_validate_geometry(vdc_t *vdc) buf_t *buf; /* BREAD requests need to be in a buf_t structure */ dev_t dev; int rv, rval; - struct dk_label label; + struct dk_label *label; struct dk_geom geom; struct extvtoc vtoc; efi_gpt_t *gpt; @@ -7786,7 +7875,7 @@ vdc_validate_geometry(vdc_t *vdc) return (EIO); } - VD_EFI_DEV_SET(edev, vdc, vd_process_efi_ioctl); + VDC_EFI_DEV_SET(edev, vdc, vd_process_efi_ioctl); rv = vd_efi_alloc_and_read(&edev, &gpt, &gpe); @@ -7870,14 +7959,15 @@ vdc_validate_geometry(vdc_t *vdc) /* * Read disk label from start of disk */ + label = kmem_alloc(vdc->vdisk_bsize, KM_SLEEP); buf = kmem_alloc(sizeof (buf_t), KM_SLEEP); bioinit(buf); - buf->b_un.b_addr = (caddr_t)&label; - buf->b_bcount = DK_LABEL_SIZE; + buf->b_un.b_addr = (caddr_t)label; + buf->b_bcount = vdc->vdisk_bsize; buf->b_flags = B_BUSY | B_READ; buf->b_dev = cmpdev(dev); - rv = vdc_send_request(vdc, VD_OP_BREAD, (caddr_t)&label, - DK_LABEL_SIZE, VD_SLICE_NONE, 0, CB_STRATEGY, buf, VIO_read_dir); + rv = vdc_send_request(vdc, VD_OP_BREAD, (caddr_t)label, + vdc->vdisk_bsize, VD_SLICE_NONE, 0, CB_STRATEGY, buf, VIO_read_dir); if (rv) { DMSG(vdc, 1, "[%d] Failed to read disk block 0\n", vdc->instance); @@ -7892,15 +7982,17 @@ vdc_validate_geometry(vdc_t *vdc) biofini(buf); kmem_free(buf, sizeof (buf_t)); - if (rv != 0 || label.dkl_magic != DKL_MAGIC || - label.dkl_cksum != vdc_lbl2cksum(&label)) { + if (rv != 0 || label->dkl_magic != DKL_MAGIC || + label->dkl_cksum != vdc_lbl2cksum(label)) { DMSG(vdc, 1, "[%d] Got VTOC with invalid label\n", vdc->instance); + kmem_free(label, vdc->vdisk_bsize); mutex_enter(&vdc->lock); vdc_store_label_unk(vdc); return (EINVAL); } + kmem_free(label, vdc->vdisk_bsize); mutex_enter(&vdc->lock); vdc_store_label_vtoc(vdc, &geom, &vtoc); return (0); @@ -8108,7 +8200,7 @@ vdc_store_label_vtoc(vdc_t *vdc, struct dk_geom *geom, struct extvtoc *vtoc) int i; ASSERT(MUTEX_HELD(&vdc->lock)); - ASSERT(vdc->block_size == vtoc->v_sectorsz); + ASSERT(vdc->vdisk_bsize == vtoc->v_sectorsz); vdc->vdisk_label = VD_DISK_LABEL_VTOC; bcopy(vtoc, vdc->vtoc, sizeof (struct extvtoc)); diff --git a/usr/src/uts/sun4v/io/vds.c b/usr/src/uts/sun4v/io/vds.c index 548fc0f048..45f4122465 100644 --- a/usr/src/uts/sun4v/io/vds.c +++ b/usr/src/uts/sun4v/io/vds.c @@ -119,6 +119,10 @@ #define VD_EFI_LBA_GPT 1 /* LBA of the GPT */ #define VD_EFI_LBA_GPE 2 /* LBA of the GPE */ +#define VD_EFI_DEV_SET(dev, vdsk, ioctl) \ + VDSK_EFI_DEV_SET(dev, vdsk, ioctl, \ + (vdsk)->vdisk_bsize, (vdsk)->vdisk_size) + /* * Flags defining the behavior for flushing asynchronous writes used to * performed some write I/O requests. @@ -451,13 +455,14 @@ typedef struct vd { int open_flags; /* open flags */ uint_t nslices; /* number of slices we export */ size_t vdisk_size; /* number of blocks in vdisk */ - size_t vdisk_block_size; /* size of each vdisk block */ + size_t vdisk_bsize; /* blk size of the vdisk */ vd_disk_type_t vdisk_type; /* slice or entire disk */ vd_disk_label_t vdisk_label; /* EFI or VTOC label */ vd_media_t vdisk_media; /* media type of backing dev. */ boolean_t is_atapi_dev; /* Is this an IDE CD-ROM dev? */ ushort_t max_xfer_sz; /* max xfer size in DEV_BSIZE */ - size_t block_size; /* blk size of actual device */ + size_t backend_bsize; /* blk size of backend device */ + int vio_bshift; /* shift for blk convertion */ boolean_t volume; /* is vDisk backed by volume */ boolean_t zvol; /* is vDisk backed by a zvol */ boolean_t file; /* is vDisk backed by a file? */ @@ -506,21 +511,20 @@ typedef struct vd { * followed by a GPT (efi_gpt_t) and a GPE (efi_gpe_t). * */ -#define VD_LABEL_VTOC_SIZE \ - P2ROUNDUP(sizeof (struct dk_label), DEV_BSIZE) +#define VD_LABEL_VTOC_SIZE(lba) \ + P2ROUNDUP(sizeof (struct dk_label), (lba)) -#define VD_LABEL_EFI_SIZE \ - P2ROUNDUP(DEV_BSIZE + sizeof (efi_gpt_t) + \ - sizeof (efi_gpe_t) * VD_MAXPART, DEV_BSIZE) +#define VD_LABEL_EFI_SIZE(lba) \ + P2ROUNDUP(2 * (lba) + sizeof (efi_gpe_t) * VD_MAXPART, \ + (lba)) #define VD_LABEL_VTOC(vd) \ ((struct dk_label *)(void *)((vd)->flabel)) -#define VD_LABEL_EFI_GPT(vd) \ - ((efi_gpt_t *)(void *)((vd)->flabel + DEV_BSIZE)) -#define VD_LABEL_EFI_GPE(vd) \ - ((efi_gpe_t *)(void *)((vd)->flabel + DEV_BSIZE + \ - sizeof (efi_gpt_t))) +#define VD_LABEL_EFI_GPT(vd, lba) \ + ((efi_gpt_t *)(void *)((vd)->flabel + (lba))) +#define VD_LABEL_EFI_GPE(vd, lba) \ + ((efi_gpe_t *)(void *)((vd)->flabel + 2 * (lba))) typedef struct vds_operation { @@ -757,6 +761,7 @@ vd_dskimg_io_params(vd_t *vd, int slice, size_t *blkp, size_t *lenp) ASSERT(vd->file || VD_DSKIMG(vd)); ASSERT(len > 0); + ASSERT(vd->vdisk_bsize == DEV_BSIZE); /* * If a file is exported as a slice then we don't care about the vtoc. @@ -797,7 +802,6 @@ vd_dskimg_io_params(vd_t *vd, int slice, size_t *blkp, size_t *lenp) ASSERT(vd->vtoc.v_sectorsz == DEV_BSIZE); } else { ASSERT(vd->vdisk_label == VD_DISK_LABEL_EFI); - ASSERT(vd->vdisk_block_size == DEV_BSIZE); } if (blk >= vd->slices[slice].nblocks) { @@ -875,6 +879,7 @@ vd_dskimg_rw(vd_t *vd, int slice, int operation, caddr_t data, size_t offset, ASSERT(vd->file || VD_DSKIMG(vd)); ASSERT(len > 0); + ASSERT(vd->vdisk_bsize == DEV_BSIZE); if ((status = vd_dskimg_io_params(vd, slice, &offset, &len)) != 0) return ((status == ENODATA)? 0: -1); @@ -941,13 +946,14 @@ vd_dskimg_rw(vd_t *vd, int slice, int operation, caddr_t data, size_t offset, * * Parameters: * disk_size - the disk size in bytes + * bsize - the disk block size in bytes * label - the returned default label. * * Return Code: * none. */ static void -vd_build_default_label(size_t disk_size, struct dk_label *label) +vd_build_default_label(size_t disk_size, size_t bsize, struct dk_label *label) { size_t size; char unit; @@ -1005,7 +1011,7 @@ vd_build_default_label(size_t disk_size, struct dk_label *label) } label->dkl_pcyl = disk_size / - (label->dkl_nsect * label->dkl_nhead * DEV_BSIZE); + (label->dkl_nsect * label->dkl_nhead * bsize); if (label->dkl_pcyl == 0) label->dkl_pcyl = 1; @@ -1027,7 +1033,7 @@ vd_build_default_label(size_t disk_size, struct dk_label *label) label->dkl_nhead, label->dkl_nsect); PR0("provided disk size: %ld bytes\n", (uint64_t) (label->dkl_pcyl * label->dkl_nhead * - label->dkl_nsect * DEV_BSIZE)); + label->dkl_nsect * bsize)); vd_get_readable_size(disk_size, &size, &unit); @@ -1230,6 +1236,8 @@ vd_dskimg_read_devid(vd_t *vd, ddi_devid_t *devid) uint_t chksum; int status, sz; + ASSERT(vd->vdisk_bsize == DEV_BSIZE); + if ((status = vd_dskimg_get_devid_block(vd, &blk)) != 0) return (status); @@ -1304,6 +1312,8 @@ vd_dskimg_write_devid(vd_t *vd, ddi_devid_t devid) size_t blk; int status; + ASSERT(vd->vdisk_bsize == DEV_BSIZE); + if (devid == NULL) { /* nothing to write */ return (0); @@ -1371,12 +1381,12 @@ vd_do_scsi_rdwr(vd_t *vd, int operation, caddr_t data, size_t blk, size_t len) ASSERT(!vd->file); ASSERT(!vd->volume); - ASSERT(vd->vdisk_block_size > 0); + ASSERT(vd->vdisk_bsize > 0); max_sectors = vd->max_xfer_sz; - nblk = (len / vd->vdisk_block_size); + nblk = (len / vd->vdisk_bsize); - if (len % vd->vdisk_block_size != 0) + if (len % vd->vdisk_bsize != 0) return (EINVAL); /* @@ -1414,7 +1424,7 @@ vd_do_scsi_rdwr(vd_t *vd, int operation, caddr_t data, size_t blk, size_t len) } ucmd.uscsi_cdb = (caddr_t)&cdb; ucmd.uscsi_bufaddr = data; - ucmd.uscsi_buflen = nsectors * vd->block_size; + ucmd.uscsi_buflen = nsectors * vd->backend_bsize; ucmd.uscsi_timeout = vd_scsi_rdwr_timeout; /* * Set flags so that the command is isolated from normal @@ -1459,7 +1469,7 @@ vd_do_scsi_rdwr(vd_t *vd, int operation, caddr_t data, size_t blk, size_t len) blk += nsectors; nblk -= nsectors; - data += nsectors * vd->vdisk_block_size; /* SECSIZE */ + data += nsectors * vd->vdisk_bsize; } return (status); @@ -1498,7 +1508,7 @@ vd_scsi_rdwr(vd_t *vd, int operation, caddr_t data, size_t vblk, size_t vlen) size_t plen; /* length of data to be read from physical device */ char *buf; /* buffer area to fit physical device's block size */ - if (vd->block_size == 0) { + if (vd->backend_bsize == 0) { /* * The block size was not available during the attach, * try to update it now. @@ -1514,10 +1524,10 @@ vd_scsi_rdwr(vd_t *vd, int operation, caddr_t data, size_t vblk, size_t vlen) * and adjust the block to be read from and the amount of data to * read to correspond with the device's block size. */ - if (vd->vdisk_block_size == vd->block_size) + if (vd->vdisk_bsize == vd->backend_bsize) return (vd_do_scsi_rdwr(vd, operation, data, vblk, vlen)); - if (vd->vdisk_block_size > vd->block_size) + if (vd->vdisk_bsize > vd->backend_bsize) return (EINVAL); /* @@ -1540,23 +1550,23 @@ vd_scsi_rdwr(vd_t *vd, int operation, caddr_t data, size_t vblk, size_t vlen) * v v * --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+- virtual disk: * | | | |XX|XX|XX|XX|XX|XX| | | | | | } block size is - * --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+- vd->vdisk_block_size + * --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+- vd->vdisk_bsize * : : : : * >:==:< delta : : * : : : : * --+-----+-----+-----+-----+-----+-----+-----+-- physical disk: * | |YY:YY|YYYYY|YYYYY|YY:YY| | | } block size is - * --+-----+-----+-----+-----+-----+-----+-----+-- vd->block_size + * --+-----+-----+-----+-----+-----+-----+-----+-- vd->backend_bsize * ^ ^ * |<--------------------->| * | plen * pblk */ /* END CSTYLED */ - pblk = (vblk * vd->vdisk_block_size) / vd->block_size; - delta = (vblk * vd->vdisk_block_size) - (pblk * vd->block_size); - pnblk = ((delta + vlen - 1) / vd->block_size) + 1; - plen = pnblk * vd->block_size; + pblk = (vblk * vd->vdisk_bsize) / vd->backend_bsize; + delta = (vblk * vd->vdisk_bsize) - (pblk * vd->backend_bsize); + pnblk = ((delta + vlen - 1) / vd->backend_bsize) + 1; + plen = pnblk * vd->backend_bsize; PR2("vblk %lx:pblk %lx: vlen %ld:plen %ld", vblk, pblk, vlen, plen); @@ -1591,7 +1601,7 @@ static ssize_t vd_slice_flabel_read(vd_t *vd, caddr_t data, size_t offset, size_t length) { size_t n = 0; - uint_t limit = vd->flabel_limit * DEV_BSIZE; + uint_t limit = vd->flabel_limit * vd->vdisk_bsize; ASSERT(vd->vdisk_type == VD_DISK_TYPE_SLICE); ASSERT(vd->flabel != NULL); @@ -1646,7 +1656,7 @@ vd_slice_flabel_read(vd_t *vd, caddr_t data, size_t offset, size_t length) static ssize_t vd_slice_flabel_write(vd_t *vd, caddr_t data, size_t offset, size_t length) { - uint_t limit = vd->flabel_limit * DEV_BSIZE; + uint_t limit = vd->flabel_limit * vd->vdisk_bsize; struct dk_label *label; struct dk_geom geom; struct extvtoc vtoc; @@ -1663,7 +1673,7 @@ vd_slice_flabel_write(vd_t *vd, caddr_t data, size_t offset, size_t length) * write was successful, but note that nothing is actually overwritten. */ if (vd->vdisk_label == VD_DISK_LABEL_VTOC && - offset == 0 && length == DEV_BSIZE) { + offset == 0 && length == vd->vdisk_bsize) { label = (void *)data; /* check that this is a valid label */ @@ -1721,7 +1731,7 @@ vd_slice_flabel_write(vd_t *vd, caddr_t data, size_t offset, size_t length) * Return the starting block relative to the vdisk * backend for the remaining operation. * lengthp - pointer to the number of bytes to read or write. - * This should be a multiple of DEV_BSIZE. Return the + * This should be a multiple of vdisk_bsize. Return the * remaining number of bytes to read or write. * * Return Code: @@ -1739,6 +1749,7 @@ vd_slice_fake_rdwr(vd_t *vd, int slice, int operation, caddr_t *datap, size_t ablk, asize, aoff, alen; ssize_t n; int sec, status; + size_t bsize = vd->vdisk_bsize; ASSERT(vd->vdisk_type == VD_DISK_TYPE_SLICE); ASSERT(slice != 0); @@ -1759,23 +1770,23 @@ vd_slice_fake_rdwr(vd_t *vd, int slice, int operation, caddr_t *datap, return (EIO); } - if (length % DEV_BSIZE != 0) + if (length % bsize != 0) return (EINVAL); /* handle any I/O with the fake label */ if (operation == VD_OP_BWRITE) - n = vd_slice_flabel_write(vd, data, blk * DEV_BSIZE, length); + n = vd_slice_flabel_write(vd, data, blk * bsize, length); else - n = vd_slice_flabel_read(vd, data, blk * DEV_BSIZE, length); + n = vd_slice_flabel_read(vd, data, blk * bsize, length); if (n == -1) return (EINVAL); - ASSERT(n % DEV_BSIZE == 0); + ASSERT(n % bsize == 0); /* adjust I/O arguments */ data += n; - blk += n / DEV_BSIZE; + blk += n / bsize; length -= n; /* check if there's something else to process */ @@ -1791,7 +1802,7 @@ vd_slice_fake_rdwr(vd_t *vd, int slice, int operation, caddr_t *datap, } if (vd->vdisk_label == VD_DISK_LABEL_EFI) { - asize = EFI_MIN_RESV_SIZE + 33; + asize = EFI_MIN_RESV_SIZE + (EFI_MIN_ARRAY_SIZE / bsize) + 1; ablk = vd->vdisk_size - asize; } else { ASSERT(vd->vdisk_label == VD_DISK_LABEL_VTOC); @@ -1802,7 +1813,7 @@ vd_slice_fake_rdwr(vd_t *vd, int slice, int operation, caddr_t *datap, asize = vd->dk_geom.dkg_acyl * csize; } - alen = length / DEV_BSIZE; + alen = length / bsize; aoff = blk; /* if we have reached the last block then the I/O is completed */ @@ -1834,10 +1845,10 @@ vd_slice_fake_rdwr(vd_t *vd, int slice, int operation, caddr_t *datap, alen = ablk + asize - aoff; } - alen *= DEV_BSIZE; + alen *= bsize; if (operation == VD_OP_BREAD) { - bzero(data + (aoff - blk) * DEV_BSIZE, alen); + bzero(data + (aoff - blk) * bsize, alen); if (vd->vdisk_label == VD_DISK_LABEL_VTOC) { /* check if we read backup labels */ @@ -1848,9 +1859,9 @@ vd_slice_fake_rdwr(vd_t *vd, int slice, int operation, caddr_t *datap, for (sec = 1; (sec < 5 * 2 + 1); sec += 2) { if (ablk + sec >= blk && - ablk + sec < blk + (length / DEV_BSIZE)) { + ablk + sec < blk + (length / bsize)) { bcopy(label, data + - (ablk + sec - blk) * DEV_BSIZE, + (ablk + sec - blk) * bsize, sizeof (struct dk_label)); } } @@ -1899,6 +1910,8 @@ vd_bio_task(void *arg) ssize_t resid; int status; + ASSERT(vd->vdisk_bsize == DEV_BSIZE); + if (vd->zvol) { status = ldi_strategy(vd->ldi_handle[0], buf); @@ -2162,6 +2175,9 @@ vd_start_bio(vd_task_t *task) buf->b_flags |= B_WRITE; } + /* convert VIO block number to buf block number */ + buf->b_lblkno = offset << vd->vio_bshift; + request->status = ldi_strategy(vd->ldi_handle[slice], buf); } @@ -3101,7 +3117,8 @@ vd_do_slice_ioctl(vd_t *vd, int cmd, void *ioctl_arg) switch (cmd) { case DKIOCGETEFI: len = vd_slice_flabel_read(vd, - (caddr_t)dk_ioc->dki_data, lba * DEV_BSIZE, len); + (caddr_t)dk_ioc->dki_data, + lba * vd->vdisk_bsize, len); ASSERT(len > 0); @@ -3237,7 +3254,8 @@ vd_dskimg_validate_geometry(vd_t *vd) } vd->vdisk_label = VD_DISK_LABEL_UNK; - vd_build_default_label(vd->dskimg_size, &label); + vd_build_default_label(vd->dskimg_size, vd->vdisk_bsize, + &label); status = EINVAL; } else { vd->vdisk_label = VD_DISK_LABEL_VTOC; @@ -3835,7 +3853,7 @@ vd_get_capacity(vd_task_t *task) request->status = 0; - vd_cap.vdisk_block_size = vd->vdisk_block_size; + vd_cap.vdisk_block_size = vd->vdisk_bsize; vd_cap.vdisk_size = vd->vdisk_size; if ((rv = ldc_mem_copy(vd->ldc_handle, (char *)&vd_cap, 0, &nbytes, @@ -4480,7 +4498,7 @@ vd_process_attr_msg(vd_t *vd, vio_msg_t *msg, size_t msglen) * Must first get the maximum transfer size in bytes. */ size_t max_xfer_bytes = attr_msg->vdisk_block_size ? - attr_msg->vdisk_block_size*attr_msg->max_xfer_sz : + attr_msg->vdisk_block_size * attr_msg->max_xfer_sz : attr_msg->max_xfer_sz; size_t max_inband_msglen = sizeof (vd_dring_inband_msg_t) + @@ -4506,7 +4524,7 @@ vd_process_attr_msg(vd_t *vd, vio_msg_t *msg, size_t msglen) } /* Return the device's block size and max transfer size to the client */ - attr_msg->vdisk_block_size = vd->vdisk_block_size; + attr_msg->vdisk_block_size = vd->vdisk_bsize; attr_msg->max_xfer_sz = vd->max_xfer_sz; attr_msg->vdisk_size = vd->vdisk_size; @@ -5442,7 +5460,7 @@ vd_dskimg_is_iso_image(vd_t *vd) * Standard Identifier and is set to CD001 for a CD-ROM compliant * to the ISO 9660 standard. */ - sec = (ISO_VOLDESC_SEC * ISO_SECTOR_SIZE) / vd->vdisk_block_size; + sec = (ISO_VOLDESC_SEC * ISO_SECTOR_SIZE) / vd->vdisk_bsize; rv = vd_dskimg_rw(vd, VD_SLICE_NONE, VD_OP_BREAD, (caddr_t)iso_buf, sec, ISO_SECTOR_SIZE); @@ -5507,16 +5525,13 @@ vd_setup_full_disk(vd_t *vd) ASSERT(vd->vdisk_type == VD_DISK_TYPE_DISK); - vd->vdisk_block_size = DEV_BSIZE; - /* set the disk size, block size and the media type of the disk */ status = vd_backend_check_size(vd); if (status != 0) { if (!vd->scsi) { /* unexpected failure */ - PRN("ldi_ioctl(DKIOCGMEDIAINFO) returned errno %d", - status); + PRN("Failed to check backend size (errno %d)", status); return (status); } @@ -5526,7 +5541,8 @@ vd_setup_full_disk(vd_t *vd) * size of the disk and the block size. */ vd->vdisk_size = VD_SIZE_UNKNOWN; - vd->block_size = 0; + vd->vdisk_bsize = 0; + vd->backend_bsize = 0; vd->vdisk_media = VD_MEDIA_FIXED; } @@ -5697,7 +5713,7 @@ vd_setup_partition_vtoc(vd_t *vd) vd->vtoc.v_part[VD_ENTIRE_DISK_SLICE].p_size = vd->dk_geom.dkg_ncyl * csize; - vd_get_readable_size(vd->vdisk_size * vd->vdisk_block_size, + vd_get_readable_size(vd->vdisk_size * vd->vdisk_bsize, &size, &unit); /* @@ -5723,7 +5739,7 @@ vd_setup_partition_vtoc(vd_t *vd) /* create a fake label from the vtoc and geometry */ vd->flabel_limit = (uint_t)csize; - vd->flabel_size = VD_LABEL_VTOC_SIZE; + vd->flabel_size = VD_LABEL_VTOC_SIZE(vd->vdisk_bsize); vd->flabel = kmem_zalloc(vd->flabel_size, KM_SLEEP); vd_vtocgeom_to_label(&vd->vtoc, &vd->dk_geom, VD_LABEL_VTOC(vd)); @@ -5741,7 +5757,7 @@ vd_setup_partition_vtoc(vd_t *vd) * as a slice without the addition of any metadata. * * So when exporting the disk as an EFI disk, we fake a disk with the following - * layout: + * layout: (assuming the block size is 512 bytes) * * flabel +--- flabel_limit * <------> v @@ -5776,9 +5792,8 @@ vd_setup_partition_vtoc(vd_t *vd) * - blocks 34+N+1 to P define a fake reserved partition and backup label, it * returns 0 * - * Note: if the backend size is not a multiple of the vdisk block size - * (DEV_BSIZE = 512 byte) then the very end of the backend will not map to - * any block of the virtual disk. + * Note: if the backend size is not a multiple of the vdisk block size then + * the very end of the backend will not map to any block of the virtual disk. */ static int vd_setup_partition_efi(vd_t *vd) @@ -5788,23 +5803,35 @@ vd_setup_partition_efi(vd_t *vd) struct uuid uuid = EFI_USR; struct uuid efi_reserved = EFI_RESERVED; uint32_t crc; - uint64_t s0_start, s0_end; + uint64_t s0_start, s0_end, first_u_lba; + size_t bsize; - vd->flabel_limit = 34; - vd->flabel_size = VD_LABEL_EFI_SIZE; + ASSERT(vd->vdisk_bsize > 0); + + bsize = vd->vdisk_bsize; + /* + * The minimum size for the label is 16K (EFI_MIN_ARRAY_SIZE) + * for GPEs plus one block for the GPT and one for PMBR. + */ + first_u_lba = (EFI_MIN_ARRAY_SIZE / bsize) + 2; + vd->flabel_limit = (uint_t)first_u_lba; + vd->flabel_size = VD_LABEL_EFI_SIZE(bsize); vd->flabel = kmem_zalloc(vd->flabel_size, KM_SLEEP); - gpt = VD_LABEL_EFI_GPT(vd); - gpe = VD_LABEL_EFI_GPE(vd); + gpt = VD_LABEL_EFI_GPT(vd, bsize); + gpe = VD_LABEL_EFI_GPE(vd, bsize); - /* adjust the vdisk_size, we emulate the first 34 blocks */ - vd->vdisk_size += 34; - s0_start = 34; + /* + * Adjust the vdisk_size, we emulate the first few blocks + * for the disk label. + */ + vd->vdisk_size += first_u_lba; + s0_start = first_u_lba; s0_end = vd->vdisk_size - 1; gpt->efi_gpt_Signature = LE_64(EFI_SIGNATURE); gpt->efi_gpt_Revision = LE_32(EFI_VERSION_CURRENT); gpt->efi_gpt_HeaderSize = LE_32(sizeof (efi_gpt_t)); - gpt->efi_gpt_FirstUsableLBA = LE_64(34ULL); + gpt->efi_gpt_FirstUsableLBA = LE_64(first_u_lba); gpt->efi_gpt_PartitionEntryLBA = LE_64(2ULL); gpt->efi_gpt_SizeOfPartitionEntry = LE_32(sizeof (efi_gpe_t)); @@ -5834,7 +5861,8 @@ vd_setup_partition_efi(vd_t *vd) gpt->efi_gpt_LastUsableLBA = LE_64(vd->vdisk_size - 1); /* adjust the vdisk size for the backup GPT and GPE */ - vd->vdisk_size += 33; + vd->vdisk_size += (EFI_MIN_ARRAY_SIZE / bsize) + 1; + gpt->efi_gpt_AlternateLBA = LE_64(vd->vdisk_size - 1); CRC32(crc, gpe, sizeof (efi_gpe_t) * VD_MAXPART, -1U, crc32_table); gpt->efi_gpt_PartitionEntryArrayCRC32 = LE_32(~crc); @@ -5854,7 +5882,6 @@ static int vd_setup_backend_vnode(vd_t *vd) { int rval, status; - vattr_t vattr; dev_t dev; char *file_path = vd->device_path; ldi_handle_t lhandle; @@ -5874,20 +5901,6 @@ vd_setup_backend_vnode(vd_t *vd) */ vd->file = B_TRUE; - vattr.va_mask = AT_SIZE; - if ((status = VOP_GETATTR(vd->file_vnode, &vattr, 0, kcred, NULL)) - != 0) { - PRN("VOP_GETATTR(%s) = errno %d", file_path, status); - return (EIO); - } - - vd->dskimg_size = vattr.va_size; - - if (vd->file_vnode->v_flag & VNOMAP) { - PRN("File %s cannot be mapped", file_path); - return (EIO); - } - vd->max_xfer_sz = maxphys / DEV_BSIZE; /* default transfer size */ /* @@ -5938,10 +5951,6 @@ vd_setup_slice_image(vd_t *vd) struct dk_label label; int status; - /* sector size = block size = DEV_BSIZE */ - vd->block_size = DEV_BSIZE; - vd->vdisk_block_size = DEV_BSIZE; - vd->vdisk_size = vd->dskimg_size / DEV_BSIZE; vd->vdisk_media = VD_MEDIA_FIXED; vd->vdisk_label = (vd_slice_label == VD_DISK_LABEL_UNK)? vd_file_slice_label : vd_slice_label; @@ -5956,7 +5965,8 @@ vd_setup_slice_image(vd_t *vd) * adjust the vtoc so that it defines a single-slice * disk. */ - vd_build_default_label(vd->dskimg_size, &label); + vd_build_default_label(vd->dskimg_size, vd->vdisk_bsize, + &label); vd_label_to_vtocgeom(&label, &vd->vtoc, &vd->dk_geom); status = vd_setup_partition_vtoc(vd); } @@ -5970,6 +5980,12 @@ vd_setup_disk_image(vd_t *vd) int status; char *backend_path = vd->device_path; + if ((status = vd_backend_check_size(vd)) != 0) { + PRN("Fail to check size of %s (errno %d)", + backend_path, status); + return (EIO); + } + /* size should be at least sizeof(dk_label) */ if (vd->dskimg_size < sizeof (struct dk_label)) { PRN("Size of file has to be at least %ld bytes", @@ -5977,11 +5993,6 @@ vd_setup_disk_image(vd_t *vd) return (EIO); } - /* sector size = block size = DEV_BSIZE */ - vd->block_size = DEV_BSIZE; - vd->vdisk_block_size = DEV_BSIZE; - vd->vdisk_size = vd->dskimg_size / DEV_BSIZE; - /* * Find and validate the geometry of a disk image. */ @@ -5997,7 +6008,7 @@ vd_setup_disk_image(vd_t *vd) * of the ISO image (images for both drive types are stored * in the ISO-9600 format). CDs can store up to just under 1Gb */ - if ((vd->vdisk_size * vd->vdisk_block_size) > ONE_GIGABYTE) + if ((vd->vdisk_size * vd->vdisk_bsize) > ONE_GIGABYTE) vd->vdisk_media = VD_MEDIA_DVD; else vd->vdisk_media = VD_MEDIA_CD; @@ -6179,14 +6190,6 @@ vd_setup_backend_ldi(vd_t *vd) if (vd->vdisk_type == VD_DISK_TYPE_DISK) { if (vd->volume) { - /* get size of backing device */ - if (ldi_get_size(vd->ldi_handle[0], &vd->dskimg_size) != - DDI_SUCCESS) { - PRN("ldi_get_size() failed for %s", - device_path); - return (EIO); - } - /* setup disk image */ return (vd_setup_disk_image(vd)); } @@ -6220,14 +6223,6 @@ vd_setup_single_slice_disk(vd_t *vd) char *device_path = vd->device_path; struct vtoc vtoc; - /* Get size of backing device */ - if (ldi_get_size(vd->ldi_handle[0], &vd->vdisk_size) != DDI_SUCCESS) { - PRN("ldi_get_size() failed for %s", device_path); - return (EIO); - } - vd->vdisk_size = lbtodb(vd->vdisk_size); /* convert to blocks */ - vd->block_size = DEV_BSIZE; - vd->vdisk_block_size = DEV_BSIZE; vd->vdisk_media = VD_MEDIA_FIXED; if (vd->volume) { @@ -6241,6 +6236,12 @@ vd_setup_single_slice_disk(vd_t *vd) vd->vdisk_type = VD_DISK_TYPE_SLICE; vd->nslices = 1; + /* Get size of backing device */ + if ((status = vd_backend_check_size(vd)) != 0) { + PRN("Fail to check size of %s (errno %d)", device_path, status); + return (EIO); + } + /* * When exporting a slice or a device as a single slice disk, we don't * care about any partitioning exposed by the backend. The goal is just @@ -6251,7 +6252,7 @@ vd_setup_single_slice_disk(vd_t *vd) * variable. */ if (vd_slice_label == VD_DISK_LABEL_EFI || - vd->vdisk_size >= ONE_TERABYTE / DEV_BSIZE) { + vd->vdisk_size >= ONE_TERABYTE / vd->vdisk_bsize) { vd->vdisk_label = VD_DISK_LABEL_EFI; } else { status = ldi_ioctl(vd->ldi_handle[0], DKIOCGEXTVTOC, @@ -6281,8 +6282,8 @@ vd_setup_single_slice_disk(vd_t *vd) } else if (vd_slice_label == VD_DISK_LABEL_VTOC) { vd->vdisk_label = VD_DISK_LABEL_VTOC; - vd_build_default_label(vd->vdisk_size * DEV_BSIZE, - &label); + vd_build_default_label(vd->vdisk_size * vd->vdisk_bsize, + vd->vdisk_bsize, &label); vd_label_to_vtocgeom(&label, &vd->vtoc, &vd->dk_geom); } else { @@ -6302,13 +6303,50 @@ vd_setup_single_slice_disk(vd_t *vd) return (status); } +/* + * This function is invoked when setting up the vdisk backend and to process + * the VD_OP_GET_CAPACITY operation. It checks the backend size and set the + * following attributes of the vd structure: + * + * - vdisk_bsize: block size for the virtual disk used by the VIO protocol. Its + * value is 512 bytes (DEV_BSIZE) when the backend is a file, a volume or a + * CD/DVD. When the backend is a disk or a disk slice then it has the value + * of the logical block size of that disk (as returned by the DKIOCGMEDIAINFO + * ioctl). This block size is expected to be a power of 2 and a multiple of + * 512. + * + * - vdisk_size: size of the virtual disk expressed as a number of vdisk_bsize + * blocks. + * + * vdisk_size and vdisk_bsize are sent to the vdisk client during the connection + * handshake and in the result of a VD_OP_GET_CAPACITY operation. + * + * - backend_bsize: block size of the backend device. backend_bsize has the same + * value as vdisk_bsize except when the backend is a CD/DVD. In that case, + * vdisk_bsize is set to 512 (DEV_BSIZE) while backend_bsize is set to the + * effective logical block size of the CD/DVD (usually 2048). + * + * - dskimg_size: size of the backend when the backend is a disk image. This + * attribute is set only when the backend is a file or a volume, otherwise it + * is unused. + * + * - vio_bshift: number of bit to shift to convert a VIO block number (which + * uses a block size of vdisk_bsize) to a buf(9s) block number (which uses a + * block size of 512 bytes) i.e. we have vdisk_bsize = 512 x 2 ^ vio_bshift + * + * - vdisk_media: media of the virtual disk. This function only sets this + * attribute for physical disk and CD/DVD. For other backend types, this + * attribute is set in the setup function of the backend. + */ static int vd_backend_check_size(vd_t *vd) { - size_t backend_size, old_size, new_size; + size_t backend_size, backend_bsize, vdisk_bsize; + size_t old_size, new_size; struct dk_minfo minfo; vattr_t vattr; - int rval, rv; + int rval, rv, media, nshift = 0; + uint32_t n; if (vd->file) { @@ -6320,20 +6358,23 @@ vd_backend_check_size(vd_t *vd) return (rv); } backend_size = vattr.va_size; + backend_bsize = DEV_BSIZE; + vdisk_bsize = DEV_BSIZE; - } else if (vd->volume || vd->vdisk_type == VD_DISK_TYPE_SLICE) { + } else if (vd->volume) { - /* physical slice or volume (slice or full disk) */ + /* volume (slice or full disk) */ rv = ldi_get_size(vd->ldi_handle[0], &backend_size); if (rv != DDI_SUCCESS) { PR0("ldi_get_size() failed for %s", vd->device_path); return (EIO); } + backend_bsize = DEV_BSIZE; + vdisk_bsize = DEV_BSIZE; } else { - /* physical disk */ - ASSERT(vd->vdisk_type == VD_DISK_TYPE_DISK); + /* physical disk or slice */ rv = ldi_ioctl(vd->ldi_handle[0], DKIOCGMEDIAINFO, (intptr_t)&minfo, (vd->open_flags | FKIOCTL), kcred, &rval); @@ -6342,17 +6383,58 @@ vd_backend_check_size(vd_t *vd) vd->device_path, rv); return (rv); } - backend_size = minfo.dki_capacity * minfo.dki_lbsize; + + if (vd->vdisk_type == VD_DISK_TYPE_SLICE) { + rv = ldi_get_size(vd->ldi_handle[0], &backend_size); + if (rv != DDI_SUCCESS) { + PR0("ldi_get_size() failed for %s", + vd->device_path); + return (EIO); + } + } else { + ASSERT(vd->vdisk_type == VD_DISK_TYPE_DISK); + backend_size = minfo.dki_capacity * minfo.dki_lbsize; + } + + backend_bsize = minfo.dki_lbsize; + media = DK_MEDIATYPE2VD_MEDIATYPE(minfo.dki_media_type); + + /* + * If the device is a CD or a DVD then we force the vdisk block + * size to 512 bytes (DEV_BSIZE). In that case, vdisk_bsize can + * be different from backend_size. + */ + if (media == VD_MEDIA_CD || media == VD_MEDIA_DVD) + vdisk_bsize = DEV_BSIZE; + else + vdisk_bsize = backend_bsize; } + /* check vdisk block size */ + if (vdisk_bsize == 0 || vdisk_bsize % DEV_BSIZE != 0) + return (EINVAL); + old_size = vd->vdisk_size; - new_size = backend_size / DEV_BSIZE; + new_size = backend_size / vdisk_bsize; /* check if size has changed */ - if (old_size != VD_SIZE_UNKNOWN && old_size == new_size) + if (old_size != VD_SIZE_UNKNOWN && old_size == new_size && + vd->vdisk_bsize == vdisk_bsize) return (0); + /* cache info for blk conversion */ + for (n = vdisk_bsize / DEV_BSIZE; n > 1; n >>= 1) { + if ((n & 0x1) != 0) { + /* blk_size is not a power of 2 */ + return (EINVAL); + } + nshift++; + } + + vd->vio_bshift = nshift; vd->vdisk_size = new_size; + vd->vdisk_bsize = vdisk_bsize; + vd->backend_bsize = backend_bsize; if (vd->file || vd->volume) vd->dskimg_size = backend_size; @@ -6384,9 +6466,7 @@ vd_backend_check_size(vd_t *vd) } else if (!vd->file && !vd->volume) { /* physical disk */ ASSERT(vd->vdisk_type == VD_DISK_TYPE_DISK); - vd->block_size = minfo.dki_lbsize; - vd->vdisk_media = - DK_MEDIATYPE2VD_MEDIATYPE(minfo.dki_media_type); + vd->vdisk_media = media; } return (0); diff --git a/usr/src/uts/sun4v/sys/vdc.h b/usr/src/uts/sun4v/sys/vdc.h index 63b76b9d27..eecaf9a30b 100644 --- a/usr/src/uts/sun4v/sys/vdc.h +++ b/usr/src/uts/sun4v/sys/vdc.h @@ -20,7 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -98,6 +98,10 @@ extern "C" { */ #define VD_MAKE_DEV(instance, minor) ((instance << VDCUNIT_SHIFT) | minor) +#define VDC_EFI_DEV_SET(dev, vdsk, ioctl) \ + VDSK_EFI_DEV_SET(dev, vdsk, ioctl, \ + (vdsk)->vdisk_bsize, (vdsk)->vdisk_size) + /* * variables controlling how long to wait before timing out and how many * retries to attempt before giving up when communicating with vds. @@ -302,7 +306,9 @@ typedef struct vdc { uint32_t vdisk_media; /* physical media type of vDisk */ uint64_t vdisk_size; /* device size in blocks */ uint64_t max_xfer_sz; /* maximum block size of a descriptor */ - uint64_t block_size; /* device block size used */ + uint64_t vdisk_bsize; /* blk size for the virtual disk */ + uint32_t vio_bmask; /* mask to check vio blk alignment */ + int vio_bshift; /* shift for vio blk conversion */ uint64_t operations; /* bitmask of ops. server supports */ struct dk_cinfo *cinfo; /* structure to store DKIOCINFO data */ struct dk_minfo *minfo; /* structure for DKIOCGMEDIAINFO data */ diff --git a/usr/src/uts/sun4v/sys/vdsk_common.h b/usr/src/uts/sun4v/sys/vdsk_common.h index 62b45c2df4..0464964847 100644 --- a/usr/src/uts/sun4v/sys/vdsk_common.h +++ b/usr/src/uts/sun4v/sys/vdsk_common.h @@ -20,7 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -521,11 +521,11 @@ typedef struct vd_efi_dev { vd_efi_ioctl_func vdisk_ioctl; /* vdisk ioctl function */ } vd_efi_dev_t; -#define VD_EFI_DEV_SET(efi_dev, vdsk, ioctl) \ - (efi_dev).vdisk = vdsk; \ - (efi_dev).vdisk_ioctl = ioctl; \ - (efi_dev).block_size = (vdsk)->block_size; \ - (efi_dev).disk_size = (vdsk)->vdisk_size; +#define VDSK_EFI_DEV_SET(efi_dev, vdsk, ioctl, bsize, dsize) \ + (efi_dev).vdisk = vdsk; \ + (efi_dev).vdisk_ioctl = ioctl; \ + (efi_dev).block_size = bsize; \ + (efi_dev).disk_size = dsize; int vd_efi_alloc_and_read(vd_efi_dev_t *dev, efi_gpt_t **gpt, efi_gpe_t **gpe); |