int main(int argc, char **argv) { struct zbc_device_info info; unsigned long long lba = 0; struct zbc_device *dev; enum zbc_reporting_options ro = ZBC_RO_ALL; int i, ret = 1; zbc_zone_t *z, *zones = NULL; unsigned int nr_zones, nz = 0; int num = 0; char *path; /* Check command line */ if ( argc < 2 ) { usage: printf("Usage: %s [options] <dev>\n" "Options:\n" " -v : Verbose mode\n" " -n : Get only the number of zones\n" " -nz <num> : Get at most <num> zones\n" " -lba <lba> : Specify zone start LBA (default is 0)\n" " -ro <opt> : Specify reporting option: \"all\", \"empty\",\n" " \"imp_open\", \"exp_open\", \"closed\", \"full\",\n" " \"rdonly\", \"offline\", \"reset\", \"non_seq\" or \"not_wp\".\n" " Default is \"all\"\n", argv[0]); return( 1 ); } /* Parse options */ for(i = 1; i < (argc - 1); i++) { if ( strcmp(argv[i], "-v") == 0 ) { zbc_set_log_level("debug"); } else if ( strcmp(argv[i], "-n") == 0 ) { num = 1; } else if ( strcmp(argv[i], "-nz") == 0 ) { if ( i >= (argc - 1) ) { goto usage; } i++; nz = strtol(argv[i], NULL, 10); if ( nz <= 0 ) { goto usage; } } else if ( strcmp(argv[i], "-lba") == 0 ) { if ( i >= (argc - 1) ) { goto usage; } i++; lba = strtoll(argv[i], NULL, 10); } else if ( strcmp(argv[i], "-ro") == 0 ) { if ( i >= (argc - 1) ) { goto usage; } i++; if ( strcmp(argv[i], "all") == 0 ) { ro = ZBC_RO_ALL; } else if ( strcmp(argv[i], "empty") == 0 ) { ro = ZBC_RO_EMPTY; } else if ( strcmp(argv[i], "imp_open") == 0 ) { ro = ZBC_RO_IMP_OPEN; } else if ( strcmp(argv[i], "exp_open") == 0 ) { ro = ZBC_RO_EXP_OPEN; } else if ( strcmp(argv[i], "closed") == 0 ) { ro = ZBC_RO_CLOSED; } else if ( strcmp(argv[i], "full") == 0 ) { ro = ZBC_RO_FULL; } else if ( strcmp(argv[i], "rdonly") == 0 ) { ro = ZBC_RO_RDONLY; } else if ( strcmp(argv[i], "offline") == 0 ) { ro = ZBC_RO_OFFLINE; } else if ( strcmp(argv[i], "reset") == 0 ) { ro = ZBC_RO_RESET; } else if ( strcmp(argv[i], "non_seq") == 0 ) { ro = ZBC_RO_NON_SEQ; } else if ( strcmp(argv[i], "not_wp") == 0 ) { ro = ZBC_RO_NOT_WP; } else { fprintf(stderr, "Unknown zone reporting option \"%s\"\n", argv[i]); goto usage; } } else if ( argv[i][0] == '-' ) { printf("Unknown option \"%s\"\n", argv[i]); goto usage; } else { break; } } if ( i != (argc - 1) ) { goto usage; } /* Open device */ path = argv[i]; ret = zbc_open(path, O_RDONLY, &dev); if ( ret != 0 ) { return( 1 ); } ret = zbc_get_device_info(dev, &info); if ( ret < 0 ) { fprintf(stderr, "zbc_get_device_info failed\n"); goto out; } printf("Device %s: %s\n", path, info.zbd_vendor_id); printf(" %s interface, %s disk model\n", zbc_disk_type_str(info.zbd_type), zbc_disk_model_str(info.zbd_model)); printf(" %llu logical blocks of %u B\n", (unsigned long long) info.zbd_logical_blocks, (unsigned int) info.zbd_logical_block_size); printf(" %llu physical blocks of %u B\n", (unsigned long long) info.zbd_physical_blocks, (unsigned int) info.zbd_physical_block_size); printf(" %.03F GB capacity\n", (double) (info.zbd_physical_blocks * info.zbd_physical_block_size) / 1000000000); /* Get the number of zones */ ret = zbc_report_nr_zones(dev, lba, ro, &nr_zones); if ( ret != 0 ) { fprintf(stderr, "zbc_report_nr_zones at lba %llu, ro 0x%02x failed %d\n", (unsigned long long) lba, (unsigned int) ro, ret); ret = 1; goto out; } /* Print zone info */ printf(" %u zones from LBA %llu, reporting option 0x%02x\n", nr_zones, lba, ro); if ( num ) { goto out; } if ( (! nz) || (nz > nr_zones) ) { nz = nr_zones; } /* Allocate zone array */ zones = (zbc_zone_t *) malloc(sizeof(zbc_zone_t) * nz); if ( ! zones ) { fprintf(stderr, "No memory\n"); ret = 1; goto out; } memset(zones, 0, sizeof(zbc_zone_t) * nz); /* Get zone information */ ret = zbc_report_zones(dev, lba, ro, zones, &nz); if ( ret != 0 ) { fprintf(stderr, "zbc_list_zones failed %d\n", ret); ret = 1; goto out; } printf("%u / %u zones:\n", nz, nr_zones); for(i = 0; i < (int)nz; i++) { z = &zones[i]; if ( zbc_zone_conventional(z) ) { printf("Zone %05d: type 0x%x (%s), cond 0x%x (%s), LBA %llu, %llu sectors, wp N/A\n", i, zbc_zone_type(z), zbc_zone_type_str(z), zbc_zone_condition(z), zbc_zone_condition_str(z), zbc_zone_start_lba(z), zbc_zone_length(z)); } else { printf("Zone %05d: type 0x%x (%s), cond 0x%x (%s), need_reset %d, non_seq %d, LBA %llu, %llu sectors, wp %llu\n", i, zbc_zone_type(z), zbc_zone_type_str(z), zbc_zone_condition(z), zbc_zone_condition_str(z), zbc_zone_need_reset(z), zbc_zone_non_seq(z), zbc_zone_start_lba(z), zbc_zone_length(z), zbc_zone_wp_lba(z)); } } out: if ( zones ) { free(zones); } zbc_close(dev); return( ret ); }
int main(int argc, char **argv) { struct zbc_device_info info; long long z; struct zbc_device *dev; int i, lba = 0, ret = 1; zbc_zone_t *zones = NULL, *rzone = NULL;; unsigned int nr_zones, rzone_idx = -1; char *path; /* Check command line */ if ( argc < 2 ) { usage: printf("Usage: %s [options] <dev> <zone>\n" " By default <zone> is interpreted as a zone number.\n" " If the -lba option is used, <zone> is interpreted as\n" " the start LBA of the zone to reset.\n" " If <zone> is -1, all zones are reset.\n" "Options:\n" " -v : Verbose mode\n" " -lba : Interpret <zone> as a zone start LBA instead of a zone number\n", argv[0]); return( 1 ); } /* Parse options */ for(i = 1; i < (argc - 1); i++) { if ( strcmp(argv[i], "-v") == 0 ) { zbc_set_log_level("debug"); } else if ( strcmp(argv[i], "-lba") == 0 ) { lba = 1; } else if ( argv[i][0] == '-' ) { printf("Unknown option \"%s\"\n", argv[i]); goto usage; } else { break; } } if ( i != (argc - 2) ) { goto usage; } /* Open device */ path = argv[i]; ret = zbc_open(path, O_RDONLY, &dev); if ( ret != 0 ) { return( 1 ); } ret = zbc_get_device_info(dev, &info); if ( ret < 0 ) { fprintf(stderr, "zbc_get_device_info failed\n"); goto out; } printf("Device %s: %s\n", path, info.zbd_vendor_id); printf(" %s interface, %s disk model\n", zbc_disk_type_str(info.zbd_type), zbc_disk_model_str(info.zbd_model)); printf(" %llu logical blocks of %u B\n", (unsigned long long) info.zbd_logical_blocks, (unsigned int) info.zbd_logical_block_size); printf(" %llu physical blocks of %u B\n", (unsigned long long) info.zbd_physical_blocks, (unsigned int) info.zbd_physical_block_size); printf(" %.03F GB capacity\n", (double) (info.zbd_physical_blocks * info.zbd_physical_block_size) / 1000000000); /* Target zone */ z = strtoll(argv[i + 1], NULL, 10); if ( z == -1 ) { printf("Resetting all zones...\n"); } else { /* Get zone list */ ret = zbc_list_zones(dev, 0, ZBC_RO_ALL, &zones, &nr_zones); if ( ret != 0 ) { fprintf(stderr, "zbc_list_zones failed\n"); ret = 1; goto out; } /* Search target zone */ if ( lba == 0 ) { if ( (z >= 0) && (z < nr_zones) ) { rzone = &zones[z]; rzone_idx = z; } } else { for(i = 0; i < (int)nr_zones; i++) { if ( zones[i].zbz_start == (uint64_t)z ) { rzone = &zones[i]; rzone_idx = i; break; } } } if ( ! rzone ) { fprintf(stderr, "Target zone not found\n"); ret = 1; goto out; } printf("Resetting zone %d/%d, start LBA %llu...\n", rzone_idx, nr_zones, (unsigned long long) rzone->zbz_start); z = rzone->zbz_start; } /* Reset WP */ ret = zbc_reset_write_pointer(dev, z); if ( ret != 0 ) { fprintf(stderr, "zbc_reset_write_pointer failed\n"); ret = 1; } out: if ( zones ) { free(zones); } /* Close device file */ zbc_close(dev); return( ret ); }
int main(int argc, char **argv) { long long z; struct zbc_device *dev; int i, ret = 1; zbc_zone_t *zones = NULL; char *path; /* Check command line */ if ( argc < 2 ) { usage: printf("Usage: %s [option] <dev> <lba>\n" " lba -1 is to set all bit flag\n" "Options:\n" " -v : Verbose mode\n", argv[0]); return( 1 ); } /* Parse options */ for(i = 1; i < (argc - 1); i++) { if ( strcmp(argv[i], "-v") == 0 ) { zbc_set_log_level("debug"); } else if ( argv[i][0] == '-' ) { printf("Unknown option \"%s\"\n", argv[i]); goto usage; } else { break; } } if ( i != (argc - 2) ) { goto usage; } /* Open device */ path = argv[i]; z = atoll(argv[i+1]); ret = zbc_open(path, O_RDONLY, &dev); if ( ret != 0 ) { fprintf(stderr, "[TEST][ERROR],can't open device\n"); return( 1 ); } /* Close zone */ ret = zbc_close_zone(dev, (uint64_t)z); if ( ret != 0 ) { fprintf(stderr, "[TEST][ERROR],zbc_test_close_zone failed\n"); { zbc_errno_t zbc_err; const char *sk_name; const char *ascq_name; zbc_errno(dev, &zbc_err); sk_name = zbc_sk_str(zbc_err.sk); ascq_name = zbc_asc_ascq_str(zbc_err.asc_ascq); printf("[TEST][ERROR][SENSE_KEY],%s\n", sk_name); printf("[TEST][ERROR][ASC_ASCQ],%s\n", ascq_name); } ret = 1; } if ( zones ) { free(zones); } /* Close device file */ zbc_close(dev); return( ret ); }
int main(int argc, char **argv) { struct zbc_device_info info; unsigned long long lba = 0; struct zbc_device *dev; enum zbc_reporting_options ro = ZBC_RO_ALL; int i, ret = 1; int num = 0; zbc_zone_t *zones = NULL; unsigned int nr_zones; char *path; /* Check command line */ if ( argc < 2 ) { usage: printf("Usage: %s [options] <dev>\n" "Options:\n" " -v : Verbose mode\n" " -n : Get only the number of zones\n" " -lba <lba> : Specify zone start LBA (default is 0)\n" " -ro <opt> : Specify reporting option: \"all\", \"empty\",\n" " \"open\", \"rdonly\", \"full\", \"offline\",\n" " \"reset\", \"non_seq\" or \"not_wp\".\n" " Default is \"all\"\n", argv[0]); return( 1 ); } /* Parse options */ for(i = 1; i < (argc - 1); i++) { if ( strcmp(argv[i], "-v") == 0 ) { zbc_set_log_level("debug"); } else if ( strcmp(argv[i], "-n") == 0 ) { num = 1; } else if ( strcmp(argv[i], "-lba") == 0 ) { if ( i >= (argc - 1) ) { goto usage; } i++; lba = strtoll(argv[i], NULL, 10); } else if ( strcmp(argv[i], "-ro") == 0 ) { if ( i >= (argc - 1) ) { goto usage; } i++; if ( strcmp(argv[i], "all") == 0 ) { ro = ZBC_RO_ALL; } else if ( strcmp(argv[i], "full") == 0 ) { ro = ZBC_RO_FULL; } else if ( strcmp(argv[i], "open") == 0 ) { ro = ZBC_RO_OPEN; } else if ( strcmp(argv[i], "empty") == 0 ) { ro = ZBC_RO_EMPTY; } else if ( strcmp(argv[i], "rdonly") == 0 ) { ro = ZBC_RO_RDONLY; } else if ( strcmp(argv[i], "offline") == 0 ) { ro = ZBC_RO_OFFLINE; } else if ( strcmp(argv[i], "reset") == 0 ) { ro = ZBC_RO_RESET; } else if ( strcmp(argv[i], "non_seq") == 0 ) { ro = ZBC_RO_NON_SEQ; } else if ( strcmp(argv[i], "not_wp") == 0 ) { ro = ZBC_RO_NOT_WP; } else { fprintf(stderr, "Unknown zone reporting option \"%s\"\n", argv[i]); goto usage; } } else if ( argv[i][0] == '-' ) { printf("Unknown option \"%s\"\n", argv[i]); goto usage; } else { break; } } if ( i != (argc - 1) ) { goto usage; } /* Open device */ path = argv[i]; ret = zbc_open(path, O_RDONLY, &dev); if ( ret != 0 ) { return( 1 ); } ret = zbc_get_device_info(dev, &info); if ( ret < 0 ) { fprintf(stderr, "zbc_get_device_info failed\n"); goto out; } printf("Device %s: %s interface, %s disk model\n", path, zbc_disk_type_str(info.zbd_type), zbc_disk_model_str(info.zbd_model)); printf(" %llu logical blocks of %u B\n", (unsigned long long) info.zbd_logical_blocks, (unsigned int) info.zbd_logical_block_size); printf(" %llu physical blocks of %u B\n", (unsigned long long) info.zbd_physical_blocks, (unsigned int) info.zbd_physical_block_size); /* Get zone list */ ret = zbc_list_zones(dev, lba, ro, &zones, &nr_zones); if ( ret != 0 ) { fprintf(stderr, "zbc_list_zones failed\n"); ret = 1; goto out; } /* Print zone info */ printf(" %u zones from LBA %llu, reporting option 0x%02x\n", nr_zones, lba, ro); if ( ! num ) { for(i = 0; i < nr_zones; i++) { printf("Zone %05d: type 0x%x, cond 0x%x, need_reset %d, non_seq %d, LBA %11llu, %11llu sectors, wp %11llu\n", i, zones[i].zbz_type, zones[i].zbz_condition, zones[i].zbz_need_reset, zones[i].zbz_non_seq, (unsigned long long) zones[i].zbz_start, (unsigned long long) zones[i].zbz_length, (unsigned long long) zones[i].zbz_write_pointer); } } out: if ( zones ) { free(zones); } zbc_close(dev); return( ret ); }
int main(int argc, char **argv) { struct zbc_device_info info; struct zbc_device *dev; zbc_zone_t *zones = NULL; unsigned int nr_zones; long long lba; int i, z, ret = 1; char *path; /* Check command line */ if ( argc < 4 ) { usage: printf("Usage: %s [options] <dev> <zone number> <LBA (-1 for full)>\n" "Options:\n" " -v : Verbose mode\n", argv[0]); return( 1 ); } /* Parse options */ for(i = 1; i < (argc - 1); i++) { if ( strcmp(argv[i], "-v") == 0 ) { zbc_set_log_level("debug"); } else if ( argv[i][0] == '-' ) { printf("Unknown option \"%s\"\n", argv[i]); goto usage; } else { break; } } if ( i != (argc - 3) ) { goto usage; } /* Open device */ path = argv[i]; ret = zbc_open(path, O_RDONLY, &dev); if ( ret != 0 ) { return( 1 ); } ret = zbc_get_device_info(dev, &info); if ( ret < 0 ) { fprintf(stderr, "zbc_get_device_info failed\n"); goto out; } printf("Device %s: %s interface, %s disk model\n", path, zbc_disk_type_str(info.zbd_type), zbc_disk_model_str(info.zbd_model)); printf(" %llu logical blocks of %u B\n", (unsigned long long) info.zbd_logical_blocks, (unsigned int) info.zbd_logical_block_size); printf(" %llu physical blocks of %u B\n", (unsigned long long) info.zbd_physical_blocks, (unsigned int) info.zbd_physical_block_size); /* Get zone list */ ret = zbc_list_zones(dev, 0, ZBC_RO_ALL, &zones, &nr_zones); if ( ret != 0 ) { fprintf(stderr, "zbc_list_zones failed\n"); ret = 1; goto out; } /* Check target zone */ z = atoi(argv[i + 1]); if ( (z < 0) || (z > (int)nr_zones) ) { fprintf(stderr, "Invalid target zone number\n"); ret = 1; goto out; } /* Get write pointer LBA */ lba = strtoll(argv[i + 2], NULL, 10); if ( lba == -1 ) { lba = zones[z].zbz_start + zones[z].zbz_length; } printf("Setting zone %d/%d write pointer LBA to %llu...\n", z, nr_zones, (unsigned long long) lba); /* Set WP */ ret = zbc_set_write_pointer(dev, zones[z].zbz_start, lba); if ( ret != 0 ) { fprintf(stderr, "zbc_set_write_pointer failed\n"); ret = 1; } out: if ( zones ) { free(zones); } /* Close device file */ zbc_close(dev); return( ret ); }
int main(int argc, char **argv) { struct zbc_device_info info; struct zbc_device *dev = NULL; unsigned long long elapsed; unsigned long long bcount = 0; unsigned long long brate; int zidx; int fd = -1, i; ssize_t ret = 1; size_t iosize; void *iobuf = NULL; ssize_t sector_count; unsigned long long ionum = 0, iocount = 0; struct zbc_zone *zones = NULL; struct zbc_zone *iozone = NULL; unsigned int nr_zones; char *path, *file = NULL; long long sector_ofst = 0; long long sector_max = 0; int flags = O_RDONLY; /* Check command line */ if (argc < 4) { usage: printf("Usage: %s [options] <dev> <zone no> <I/O size (B)>\n" " Read a zone up to the current write pointer\n" " or the number of I/O specified is executed\n" "Options:\n" " -v : Verbose mode\n" " -dio : Use direct I/Os\n" " -nio <num> : Limit the number of I/Os to <num>\n" " -f <file> : Write the content of the zone to <file>\n" " If <file> is \"-\", the zone content is\n" " written to the standard output\n" " -ofst : sector offset from the start sector of\n" " the zone (default 0 or write pointer)\n", argv[0]); return 1; } /* Parse options */ for (i = 1; i < (argc - 1); i++) { if (strcmp(argv[i], "-v") == 0) { zbc_set_log_level("debug"); } else if (strcmp(argv[i], "-dio") == 0) { flags |= O_DIRECT; } else if (strcmp(argv[i], "-nio") == 0) { if (i >= (argc - 1)) goto usage; i++; ionum = atoi(argv[i]); if (ionum <= 0) { fprintf(stderr, "Invalid number of I/Os\n"); return 1; } } else if (strcmp(argv[i], "-f") == 0) { if (i >= (argc - 1)) goto usage; i++; file = argv[i]; } else if (strcmp(argv[i], "-ofst") == 0) { if (i >= (argc - 1)) goto usage; i++; sector_ofst = atoll(argv[i]); if (sector_ofst < 0) { fprintf(stderr, "Invalid sector offset\n"); return 1; } } else if (argv[i][0] == '-') { fprintf(stderr, "Unknown option \"%s\"\n", argv[i]); goto usage; } else { break; } } if (i != (argc - 3)) goto usage; /* Get parameters */ path = argv[i]; zidx = atoi(argv[i + 1]); if (zidx < 0) { fprintf(stderr, "Invalid zone number %s\n", argv[i + 1]); return 1; } iosize = atol(argv[i + 2]); if (!iosize) { fprintf(stderr, "Invalid I/O size %s\n", argv[i + 2]); return 1; } /* Setup signal handler */ signal(SIGQUIT, zbc_read_zone_sigcatcher); signal(SIGINT, zbc_read_zone_sigcatcher); signal(SIGTERM, zbc_read_zone_sigcatcher); /* Open device */ ret = zbc_open(path, flags, &dev); if (ret != 0) { if (ret == -ENODEV) fprintf(stderr, "Open %s failed (not a zoned block device)\n", path); else fprintf(stderr, "Open %s failed (%s)\n", path, strerror(-ret)); return 1; } zbc_get_device_info(dev, &info); printf("Device %s:\n", path); zbc_print_device_info(&info, stdout); /* Get zone list */ ret = zbc_list_zones(dev, 0, ZBC_RO_ALL, &zones, &nr_zones); if (ret != 0) { fprintf(stderr, "zbc_list_zones failed\n"); ret = 1; goto out; } /* Get target zone */ if ((unsigned int)zidx >= nr_zones) { fprintf(stderr, "Target zone not found\n"); ret = 1; goto out; } iozone = &zones[zidx]; if (zbc_zone_conventional(iozone)) printf("Target zone: Conventional zone %d / %d, " "sector %llu, %llu sectors\n", zidx, nr_zones, zbc_zone_start(iozone), zbc_zone_length(iozone)); else printf("Target zone: Zone %d / %d, type 0x%x (%s), " "cond 0x%x (%s), rwp %d, non_seq %d, " "sector %llu, %llu sectors, wp %llu\n", zidx, nr_zones, zbc_zone_type(iozone), zbc_zone_type_str(zbc_zone_type(iozone)), zbc_zone_condition(iozone), zbc_zone_condition_str(zbc_zone_condition(iozone)), zbc_zone_rwp_recommended(iozone), zbc_zone_non_seq(iozone), zbc_zone_start(iozone), zbc_zone_length(iozone), zbc_zone_wp(iozone)); /* Check I/O alignment and get an I/O buffer */ if (iosize % info.zbd_lblock_size) { fprintf(stderr, "Invalid I/O size %zu (must be a multiple of %u B)\n", iosize, (unsigned int) info.zbd_lblock_size); ret = 1; goto out; } ret = posix_memalign((void **) &iobuf, sysconf(_SC_PAGESIZE), iosize); if ( ret != 0 ) { fprintf(stderr, "No memory for I/O buffer (%zu B)\n", iosize); ret = 1; goto out; } /* Open the file to write, if any */ if (file) { if (strcmp(file, "-") == 0) { fd = fileno(stdout); printf("Writting target zone %d to standard output, " "%zu B I/Os\n", zidx, iosize); } else { fd = open(file, O_CREAT | O_TRUNC | O_LARGEFILE | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP); if (fd < 0) { fprintf(stderr, "Open file \"%s\" failed %d (%s)\n", file, errno, strerror(errno)); ret = 1; goto out; } printf("Writting target zone %d to file \"%s\", " "%zu B I/Os\n", zidx, file, iosize); } } else if (!ionum) { printf("Reading target zone %d, %zu B I/Os\n", zidx, iosize); } else { printf("Reading target zone %d, %llu I/Os of %zu B\n", zidx, ionum, iosize); } if (zbc_zone_sequential_req(iozone) && !zbc_zone_full(iozone)) sector_max = zbc_zone_wp(iozone) - zbc_zone_start(iozone); else sector_max = zbc_zone_length(iozone); elapsed = zbc_read_zone_usec(); while (!zbc_read_zone_abort && sector_ofst < sector_max) { /* Read zone */ sector_count = iosize >> 9; if (sector_ofst + sector_count > sector_max) sector_count = sector_max - sector_ofst; ret = zbc_pread(dev, iobuf, sector_count, zbc_zone_start(iozone) + sector_ofst); if (ret <= 0) { fprintf(stderr, "zbc_pread failed %zd (%s)\n", -ret, strerror(-ret)); ret = 1; break; } sector_count = ret; if (file) { /* Write zone data to output file */ ret = write(fd, iobuf, sector_count << 9); if (ret < 0) { fprintf(stderr, "Write file \"%s\" failed %d (%s)\n", file, errno, strerror(errno)); ret = 1; break; } } sector_ofst += sector_count; bcount += sector_count << 9; iocount++; ret = 0; if (ionum > 0 && iocount >= ionum) break; } elapsed = zbc_read_zone_usec() - elapsed; if (elapsed) { printf("Read %llu B (%llu I/Os) in %llu.%03llu sec\n", bcount, iocount, elapsed / 1000000, (elapsed % 1000000) / 1000); printf(" IOPS %llu\n", iocount * 1000000 / elapsed); brate = bcount * 1000000 / elapsed; printf(" BW %llu.%03llu MB/s\n", brate / 1000000, (brate % 1000000) / 1000); } else { printf("Read %llu B (%llu I/Os)\n", bcount, iocount); } out: if ( file && (fd > 0) ) { if (fd != fileno(stdout)) close(fd); if (ret != 0) unlink(file); } if (iobuf) free(iobuf); if (zones) free(zones); zbc_close(dev); return ret; }
int main(int argc, char **argv) { struct zbc_device_info info; struct zbc_device *dev = NULL; unsigned long long elapsed; unsigned long long bcount = 0; unsigned long long fsize, brate; struct stat st; int zidx; int floop = 0, fd = -1, i, ret = 1; size_t iosize, ioalign; void *iobuf = NULL; uint32_t lba_count = 0; int iocount = 0, ionum = 0; struct zbc_zone *zones = NULL; struct zbc_zone *iozone = NULL; unsigned int nr_zones; char *path, *file = NULL; long long lba_ofst = 0; int flush = 0; /* Check command line */ if ( argc < 4 ) { usage: printf("Usage: %s [options] <dev> <zone no> <I/O size>\n" " Write into a zone from the current write pointer until\n" " the zone is full or the number of I/O specified is executed\n" "Options:\n" " -v : Verbose mode\n" " -s : (sync) Run zbc_flush after writing\n" " -nio <num> : Limit the number of I/O executed to <num>\n" " -f <file> : Write the content of <file>\n" " -loop : If a file is specified, repeatedly write the\n" " file to the zone until the zone is full.\n" " -lba : lba offset, from given zone <zone no> starting lba, where to write.\n", argv[0]); return( 1 ); } /* Parse options */ for(i = 1; i < (argc - 1); i++) { if ( strcmp(argv[i], "-v") == 0 ) { zbc_set_log_level("debug"); } else if ( strcmp(argv[i], "-s") == 0 ) { flush = 1; } else if ( strcmp(argv[i], "-nio") == 0 ) { if ( i >= (argc - 1) ) { goto usage; } i++; ionum = atoi(argv[i]); if ( ionum <= 0 ) { fprintf(stderr, "Invalid number of I/Os\n"); return( 1 ); } } else if ( strcmp(argv[i], "-f") == 0 ) { if ( i >= (argc - 1) ) { goto usage; } i++; file = argv[i]; } else if ( strcmp(argv[i], "-loop") == 0 ) { floop = 1; } else if ( strcmp(argv[i], "-lba") == 0 ) { if ( i >= (argc - 1) ) { goto usage; } i++; lba_ofst = atoll(argv[i]); if ( lba_ofst < 0 ) { fprintf(stderr, "Invalid negative LBA offset\n"); return( 1 ); } } else if ( argv[i][0] == '-' ) { fprintf(stderr, "Unknown option \"%s\"\n", argv[i]); goto usage; } else { break; } } if ( i != (argc - 3) ) { goto usage; } /* Get parameters */ path = argv[i]; zidx = atoi(argv[i + 1]); if ( zidx < 0 ) { fprintf(stderr, "Invalid zone number %s\n", argv[i + 1]); ret = 1; goto out; } iosize = atol(argv[i + 2]); if ( ! iosize ) { fprintf(stderr, "Invalid I/O size %s\n", argv[i + 2]); ret = 1; goto out; } /* Setup signal handler */ signal(SIGQUIT, zbc_write_zone_sigcatcher); signal(SIGINT, zbc_write_zone_sigcatcher); signal(SIGTERM, zbc_write_zone_sigcatcher); /* Open device */ ret = zbc_open(path, O_WRONLY, &dev); if ( ret != 0 ) { return( 1 ); } ret = zbc_get_device_info(dev, &info); if ( ret < 0 ) { fprintf(stderr, "zbc_get_device_info failed\n"); goto out; } /* Get zone list */ ret = zbc_list_zones(dev, 0, ZBC_RO_ALL, &zones, &nr_zones); if ( ret != 0 ) { fprintf(stderr, "zbc_list_zones failed\n"); ret = 1; goto out; } /* Get target zone */ if ( zidx >= (int)nr_zones ) { fprintf(stderr, "Target zone not found\n"); ret = 1; goto out; } iozone = &zones[zidx]; printf("Device %s: %s interface, %s disk model\n", path, zbc_disk_type_str(info.zbd_type), zbc_disk_model_str(info.zbd_model)); printf(" %llu logical blocks of %u B\n", (unsigned long long) info.zbd_logical_blocks, (unsigned int) info.zbd_logical_block_size); printf(" %llu physical blocks of %u B\n", (unsigned long long) info.zbd_physical_blocks, (unsigned int) info.zbd_physical_block_size); printf("Target zone: Zone %d / %d, type 0x%x, cond 0x%x, need_reset %d, non_seq %d, LBA %llu, %llu sectors, wp %llu\n", zidx, nr_zones, iozone->zbz_type, iozone->zbz_condition, iozone->zbz_need_reset, iozone->zbz_non_seq, zbc_zone_start_lba(iozone), zbc_zone_length(iozone), zbc_zone_wp_lba(iozone)); /* Check I/O size alignment */ if ( zbc_zone_sequential_req(iozone) ) { ioalign = info.zbd_physical_block_size; } else { ioalign = info.zbd_logical_block_size; } if ( iosize % ioalign ) { fprintf(stderr, "Invalid I/O size %zu (must be aligned on %zu)\n", iosize, ioalign); ret = 1; goto out; } /* Get an I/O buffer */ ret = posix_memalign((void **) &iobuf, ioalign, iosize); if ( ret != 0 ) { fprintf(stderr, "No memory for I/O buffer (%zu B)\n", iosize); ret = 1; goto out; } /* Open the file to write, if any */ if ( file ) { fd = open(file, O_LARGEFILE | O_RDONLY); if ( fd < 0 ) { fprintf(stderr, "Open file \"%s\" failed %d (%s)\n", file, errno, strerror(errno)); ret = 1; goto out; } ret = fstat(fd, &st); if ( ret != 0 ) { fprintf(stderr, "Stat file \"%s\" failed %d (%s)\n", file, errno, strerror(errno)); ret = 1; goto out; } if ( S_ISREG(st.st_mode) ) { fsize = st.st_size; } else if ( S_ISBLK(st.st_mode) ) { ret = ioctl(fd, BLKGETSIZE64, &fsize); if ( ret != 0 ) { fprintf(stderr, "ioctl BLKGETSIZE64 block device \"%s\" failed %d (%s)\n", file, errno, strerror(errno)); ret = 1; goto out; } } else { fprintf(stderr, "Unsupported file \"%s\" type\n", file); ret = 1; goto out; } printf("Writting file \"%s\" (%llu B) to target zone %d, %zu B I/Os\n", file, fsize, zidx, iosize); } else if ( ! ionum ) { printf("Filling target zone %d, %zu B I/Os\n", zidx, iosize); } else { printf("Writting to target zone %d, %d I/Os of %zu B\n", zidx, ionum, iosize); } if ( ! zbc_zone_conventional(iozone) ) { lba_ofst = zbc_zone_wp_lba(iozone) - zbc_zone_start_lba(iozone); } elapsed = zbc_write_zone_usec(); while( (! zbc_write_zone_abort) && (lba_ofst < (long long)zbc_zone_length(iozone)) ) { if ( file ) { size_t ios; /* Read file */ ret = read(fd, iobuf, iosize); if ( ret < 0 ) { fprintf(stderr, "Read file \"%s\" failed %d (%s)\n", file, errno, strerror(errno)); ret = 1; break; } ios = ret; if ( ios < iosize ) { if ( floop ) { /* Rewind and read remaining of buffer */ lseek(fd, 0, SEEK_SET); ret = read(fd, iobuf + ios, iosize - ios); if ( ret < 0 ) { fprintf(stderr, "Read file \"%s\" failed %d (%s)\n", file, errno, strerror(errno)); ret = 1; break; } ios += ret; } else if ( ios ) { /* Clear end of buffer */ memset(iobuf + ios, 0, iosize - ios); } } if ( ! ios ) { /* EOF */ break; } } /* Write to zone */ lba_count = iosize / info.zbd_logical_block_size; if ( (lba_ofst + lba_count) > (long long)zbc_zone_length(iozone) ) { lba_count = zbc_zone_length(iozone) - lba_ofst; } if ( zbc_zone_conventional(iozone) ) { ret = zbc_pwrite(dev, iozone, iobuf, lba_count, lba_ofst); if ( ret > 0 ) { lba_ofst += ret; } } else { ret = zbc_write(dev, iozone, iobuf, lba_count); } if ( ret <= 0 ) { ret = 1; break; } /* Update zone write pointer */ lba_ofst += ret; if ( zbc_zone_sequential_req(iozone) ) { iozone->zbz_write_pointer += ret; } else if ( zbc_zone_sequential_pref(iozone) ) { ret = zbc_report_zones(dev, 0, ZBC_RO_ALL, zones, &nr_zones); if ( ret != 0 ) { fprintf(stderr, "zbc_report_zones failed\n"); ret = 1; goto out; } } bcount += ret * info.zbd_logical_block_size; iocount++; if ( (ionum > 0) && (iocount >= ionum) ) { break; } } elapsed = zbc_write_zone_usec() - elapsed; if ( elapsed ) { printf("Wrote %llu B (%d I/Os) in %llu.%03llu sec\n", bcount, iocount, elapsed / 1000000, (elapsed % 1000000) / 1000); printf(" IOPS %llu\n", iocount * 1000000 / elapsed); brate = bcount * 1000000 / elapsed; printf(" BW %llu.%03llu MB/s\n", brate / 1000000, (brate % 1000000) / 1000); } else { printf("Wrote %llu B (%d I/Os)\n", bcount, iocount); } if ( flush ) { printf("Flushing disk...\n"); ret = zbc_flush(dev); if ( ret != 0 ) { fprintf(stderr, "zbc_flush failed %d (%s)\n", -ret, strerror(-ret)); ret = 1; } } out: if ( iobuf ) { free(iobuf); } if ( fd > 0 ) { close(fd); } if ( zones ) { free(zones); } zbc_close(dev); return( ret ); }
int main(int argc, char **argv) { struct zbc_device_info info; struct zbc_device *dev; long long conv_num, conv_sz, zone_sz; double conv_p; int i, ret = -1; char *path; /* Check command line */ if ( argc < 5 ) { usage: printf("Usage: %s [options] <dev> <command> <command arguments>\n" "Options:\n" " -v : Verbose mode\n" "Commands:\n" " set_sz <conv zone size (MB)> <zone size (MiB)> : Specify the total size in MiB of all conventional zones\n" " and the size in MiB of zones\n" " set_ps <conv zone size (%%)> <zone size (MiB)> : Specify the percentage of the capacity to use for\n" " conventional zones and the size in MiB of zones\n", argv[0]); return( 1 ); } /* Parse options */ for(i = 1; i < (argc - 2); i++) { if ( strcmp(argv[i], "-v") == 0 ) { zbc_set_log_level("debug"); } else if ( argv[i][0] == '-' ) { fprintf(stderr, "Unknown option \"%s\"\n", argv[i]); goto usage; } else { break; } } if ( i > (argc - 2) ) { goto usage; } /* Open device */ path = argv[i]; ret = zbc_open(path, O_RDONLY, &dev); if ( ret < 0 ) { fprintf(stderr, "zbc_open failed\n"); return( 1 ); } /* Get device info */ ret = zbc_get_device_info(dev, &info); if ( ret < 0 ) { fprintf(stderr, "zbc_get_device_info failed\n"); return( 1 ); } printf("Device %s: %s\n", path, info.zbd_vendor_id); printf(" %s interface, %s disk model\n", zbc_disk_type_str(info.zbd_type), zbc_disk_model_str(info.zbd_model)); printf(" %llu logical blocks of %u B\n", (unsigned long long) info.zbd_logical_blocks, (unsigned int) info.zbd_logical_block_size); printf(" %llu physical blocks of %u B\n", (unsigned long long) info.zbd_physical_blocks, (unsigned int) info.zbd_physical_block_size); printf(" %.03F GiB capacity\n", (double) (info.zbd_physical_blocks * info.zbd_physical_block_size) / 1000000000.0); /* Process command */ printf("Setting zones:\n"); i++; if ( strcmp(argv[i], "set_sz") == 0 ) { /* Set size */ if ( i != (argc - 3) ) { goto usage; } /* Get arguments */ conv_sz = (strtoll(argv[i + 1], NULL, 10) * 1024 * 1024) / info.zbd_logical_block_size;; if ( conv_sz < 0 ) { fprintf(stderr, "Invalid conventional zones size %s\n", argv[i + 1]); ret = 1; goto out; } zone_sz = (strtoll(argv[i + 2], NULL, 10) * 1024 * 1024) / info.zbd_logical_block_size;; if ( zone_sz <= 0 ) { fprintf(stderr, "Invalid zone size %s\n", argv[i + 2]); ret = 1; goto out; } } else if ( strcmp(argv[i], "set_ps") == 0 ) { /* Set perc + num */ if ( i != (argc - 3) ) { goto usage; } /* Get arguments */ conv_p = strtof(argv[i + 1], NULL); if ( (conv_p < 0) || (conv_p >= 100.0) ) { fprintf(stderr, "Invalid capacity percentage %s for conventional zones\n", argv[i + 1]); ret = 1; goto out; } conv_sz = (long long)((double) info.zbd_logical_blocks * (double) conv_p) / 100; zone_sz = (strtoll(argv[i + 2], NULL, 10) * 1024ULL * 1024ULL) / info.zbd_logical_block_size; if ( zone_sz == 0 ) { fprintf(stderr, "Invalid zone size %s\n", argv[i + 2]); ret = 1; goto out; } } else { fprintf(stderr, "Unknown command \"%s\"\n", argv[i]); goto out; } if ( conv_sz ) { conv_num = conv_sz / zone_sz; if ( (! conv_num) || (conv_sz % zone_sz) ) { conv_num++; } } else { conv_num = 0; } conv_sz = zone_sz * conv_num; printf(" Zone size: %lld MiB (%lld sectors)\n", (zone_sz * info.zbd_logical_block_size) / (1024 * 1024), zone_sz); printf(" Conventional zones: %lld MiB (%lld sectors), %.02F %% of total capacity), %lld zones\n", (conv_sz * info.zbd_logical_block_size) / (1024 * 1024), conv_sz, 100.0 * (double)conv_sz / (double)info.zbd_logical_blocks, conv_num); printf(" Sequential zones: %llu zones\n", (info.zbd_logical_blocks - conv_sz) / zone_sz); ret = zbc_set_zones(dev, conv_sz, zone_sz); if ( ret != 0 ) { fprintf(stderr, "zbc_set_zones failed\n"); ret = 1; } out: zbc_close(dev); return( ret ); }
int main(int argc, char **argv) { struct zbc_device_info info; unsigned long long lba = 0; struct zbc_device *dev; enum zbc_reporting_options ro = ZBC_RO_ALL; int i, ret = 1; zbc_zone_t *z, *zones = NULL; unsigned int nr_zones, nz = 0, prtl = 0; int num = 0; char *path; /* Check command line */ if ( argc < 2 ) { usage: printf("Usage: %s [options] <dev>\n" "Options:\n" " -v : Verbose mode\n" " -lba <lba> : Specify zone start LBA (default is 0)\n" " -ro <opt> : Reporting Option\n" " -p : Partial bit\n", argv[0]); return( 1 ); } /* Parse options */ for(i = 1; i < (argc - 1); i++) { if ( strcmp(argv[i], "-v") == 0 ) { zbc_set_log_level("debug"); } else if ( strcmp(argv[i], "-lba") == 0 ) { if ( i >= (argc - 1) ) { goto usage; } i++; lba = strtoll(argv[i], NULL, 10); } else if ( strcmp(argv[i], "-ro") == 0 ) { if ( i >= (argc - 1) ) { goto usage; } i++; ro = atoi(argv[i]); if ( ro < 0 ) { goto usage; } } else if ( strcmp(argv[i], "-p") == 0 ) { prtl = ZBC_RO_PARTIAL; } else if ( argv[i][0] == '-' ) { printf("Unknown option \"%s\"\n", argv[i]); goto usage; } else { break; } } if ( i != (argc - 1) ) { goto usage; } /* Merging ro */ ro |= prtl; /* Open device */ path = argv[i]; ret = zbc_open(path, O_RDONLY, &dev); if ( ret != 0 ) { fprintf(stderr, "[TEST][ERROR],open device failed\n"); printf("[TEST][ERROR][SENSE_KEY],open-device-failed\n"); printf("[TEST][ERROR][ASC_ASCQ],open-device-failed\n"); return( 1 ); } ret = zbc_get_device_info(dev, &info); if ( ret < 0 ) { fprintf(stderr, "[TEST][ERROR],zbc_get_device_info failed\n"); goto out; } /* Get the number of zones */ ret = zbc_report_nr_zones(dev, lba, ro, &nr_zones); if ( ret != 0 ) { fprintf(stderr, "[TEST][ERROR],zbc_report_nr_zones at lba %llu, ro 0x%02x failed %d\n", (unsigned long long) lba, (unsigned int) ro, ret); ret = 1; goto out; } if ( num ) { goto out; } if ( (! nz) || (nz > nr_zones) ) { nz = nr_zones; } /* Allocate zone array */ zones = (zbc_zone_t *) malloc(sizeof(zbc_zone_t) * nz); if ( ! zones ) { fprintf(stderr, "[TEST][ERROR],No memory\n"); ret = 1; goto out; } memset(zones, 0, sizeof(zbc_zone_t) * nz); /* Get zone information */ ret = zbc_report_zones(dev, lba, ro, zones, &nz); if ( ret != 0 ) { fprintf(stderr, "[TEST][ERROR],zbc_report_zones failed %d\n", ret); ret = 1; goto out; } for(i = 0; i < (int)nz; i++) { z = &zones[i]; if ( zbc_zone_conventional(z) ) { printf("[ZONE_INFO],%05d,0x%x,0x%x,%llu,%llu,N/A\n", i, zbc_zone_type(z), zbc_zone_condition(z), zbc_zone_start_lba(z), zbc_zone_length(z)); } else { printf("[ZONE_INFO],%05d,0x%x,0x%x,%llu,%llu,%llu\n", i, zbc_zone_type(z), zbc_zone_condition(z), zbc_zone_start_lba(z), zbc_zone_length(z), zbc_zone_wp_lba(z)); } } out: if ( ret ) { zbc_errno_t zbc_err; const char *sk_name; const char *ascq_name; zbc_errno(dev, &zbc_err); sk_name = zbc_sk_str(zbc_err.sk); ascq_name = zbc_asc_ascq_str(zbc_err.asc_ascq); printf("[TEST][ERROR][SENSE_KEY],%s\n", sk_name); printf("[TEST][ERROR][ASC_ASCQ],%s\n", ascq_name); } if ( zones ) { free(zones); } zbc_close(dev); return( ret ); }
int main(int argc, char **argv) { char *filename = NULL; gboolean init_ret; gboolean verbose = FALSE; GError *error = NULL; int ret; GOptionEntry options[] = { { "dev", 'd', 0, G_OPTION_ARG_FILENAME, &filename, "ZBC device file", NULL }, { "interval", 'i', 0, G_OPTION_ARG_INT, &dz.interval, "Refresh interval (milliseconds)", NULL }, { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Set libzbc verbose mode", NULL }, { NULL } }; /* Init */ memset(&dz, 0, sizeof(dz)); dz.interval = DZ_INTERVAL; gtk_set_locale(); init_ret = gtk_init_with_args(&argc, &argv, "ZBC device zone state GUI", options, NULL, &error); if ( (init_ret == FALSE) || (error != NULL) ) { printf("Failed to parse command line arguments: %s\n", error->message); g_error_free(error); return( 1 ); } if ( ! filename ) { fprintf(stderr, "No ZBC device file specified\n"); return( 1 ); } if ( verbose ) { zbc_set_log_level("debug"); } dz_set_signal_handlers(); /* Open device file */ ret = zbc_open(filename, O_RDONLY, &dz.dev); if ( ret != 0 ) { fprintf(stderr, "Open device %s failed\n", filename); return( 1 ); } ret = zbc_get_device_info(dz.dev, &dz.info); if ( ret < 0 ) { fprintf(stderr, "zbc_get_device_info failed\n"); goto out; } dz.filename = filename; printf("Creating interface...\n"); /* Create GUI */ dz_if_create(); /* Main event loop */ gtk_main(); /* Cleanup GUI */ dz_if_destroy(); out: zbc_close(dz.dev); return( ret ); }
dz_dev_t * dz_open(char *path) { dz_dev_t *dzd = NULL; int i, ret; /* Get an unused device */ for(i = 0; i < DZ_MAX_DEV; i++) { if ( ! dz.dev[i].dev ) { dzd = &dz.dev[i]; break; } } if ( ! dzd ) { return( NULL ); } /* Open device file */ strncpy(dzd->path, path, sizeof(dzd->path) - 1); ret = zbc_open(dzd->path, O_RDONLY, &dzd->dev); if ( ret != 0 ) { return( NULL ); } ret = zbc_get_device_info(dzd->dev, &dzd->info); if ( ret != 0 ) { fprintf(stderr, "zbc_get_device_info failed\n"); goto out; } dzd->block_size = dz.block_size; if ( dzd->block_size ) { if ( ((unsigned int) dzd->block_size < dzd->info.zbd_logical_block_size) && (dzd->info.zbd_logical_block_size % dzd->block_size) ) { dzd->block_size = 0; } else if ( ((unsigned int) dzd->block_size >= dzd->info.zbd_logical_block_size) && (dzd->block_size % dzd->info.zbd_logical_block_size) ) { dzd->block_size = 0; } } if ( ! dzd->block_size ) { dzd->block_size = dzd->info.zbd_logical_block_size; } /* Get zone information */ ret = dz_get_zones(dzd); if ( ret != 0 ) { goto out; } dz.nr_devs++; out: if ( ret != 0 ) { dz_close(dzd); dzd = NULL; } return( dzd ); }
int main(int argc, char **argv) { struct zbc_device_info info; struct zbc_device *dev = NULL; unsigned long long elapsed; unsigned long long bcount = 0; unsigned long long brate; int zidx; int fd = -1, i, ret = 1; size_t iosize; void *iobuf = NULL; uint32_t lba_count; unsigned long long ionum = 0, iocount = 0; struct zbc_zone *zones = NULL; struct zbc_zone *iozone = NULL; unsigned int nr_zones; char *path, *file = NULL; long long lba_ofst = 0; long long lba_max = 0; int flags = O_RDONLY; /* Check command line */ if ( argc < 4 ) { usage: printf("Usage: %s [options] <dev> <zone no> <I/O size (B)>\n" " Read a zone up to the current write pointer\n" " or the number of I/O specified is executed\n" "Options:\n" " -v : Verbose mode\n" " -dio : Use direct I/Os for accessing the device\n" " -nio <num> : Limit the number of I/O executed to <num>\n" " -f <file> : Write the content of the zone to <file>\n" " If <file> is \"-\", the zone content is\n" " written to the standard output\n" " -lba : lba offset from the starting lba of the zone <zone no>.\n", argv[0]); return( 1 ); } /* Parse options */ for(i = 1; i < (argc - 1); i++) { if ( strcmp(argv[i], "-v") == 0 ) { zbc_set_log_level("debug"); } else if ( strcmp(argv[i], "-dio") == 0 ) { flags |= O_DIRECT; } else if ( strcmp(argv[i], "-nio") == 0 ) { if ( i >= (argc - 1) ) { goto usage; } i++; ionum = atoi(argv[i]); if ( ionum <= 0 ) { fprintf(stderr, "Invalid number of I/Os\n"); return( 1 ); } } else if ( strcmp(argv[i], "-f") == 0 ) { if ( i >= (argc - 1) ) { goto usage; } i++; file = argv[i]; } else if ( strcmp(argv[i], "-lba") == 0 ) { if ( i >= (argc - 1) ) { goto usage; } i++; lba_ofst = atoll(argv[i]); if ( lba_ofst < 0 ) { fprintf(stderr, "LBA offset has to be greater or equal to 0.\n"); return( 1 ); } } else if ( argv[i][0] == '-' ) { fprintf(stderr, "Unknown option \"%s\"\n", argv[i]); goto usage; } else { break; } } if ( i != (argc - 3) ) { goto usage; } /* Get parameters */ path = argv[i]; zidx = atoi(argv[i + 1]); if ( zidx < 0 ) { fprintf(stderr, "Invalid zone number %s\n", argv[i + 1]); ret = 1; goto out; } iosize = atol(argv[i + 2]); if ( ! iosize ) { fprintf(stderr, "Invalid I/O size %s\n", argv[i + 2]); ret = 1; goto out; } /* Setup signal handler */ signal(SIGQUIT, zbc_read_zone_sigcatcher); signal(SIGINT, zbc_read_zone_sigcatcher); signal(SIGTERM, zbc_read_zone_sigcatcher); /* Open device */ ret = zbc_open(path, flags, &dev); if ( ret != 0 ) { return( 1 ); } ret = zbc_get_device_info(dev, &info); if ( ret < 0 ) { fprintf(stderr, "zbc_get_device_info failed\n"); goto out; } /* Get zone list */ ret = zbc_list_zones(dev, 0, ZBC_RO_ALL, &zones, &nr_zones); if ( ret != 0 ) { fprintf(stderr, "zbc_list_zones failed\n"); ret = 1; goto out; } /* Get target zone */ if ( (unsigned int)zidx >= nr_zones ) { fprintf(stderr, "Target zone not found\n"); ret = 1; goto out; } iozone = &zones[zidx]; printf("Device %s: %s\n", path, info.zbd_vendor_id); printf(" %s interface, %s disk model\n", zbc_disk_type_str(info.zbd_type), zbc_disk_model_str(info.zbd_model)); printf(" %llu logical blocks of %u B\n", (unsigned long long) info.zbd_logical_blocks, (unsigned int) info.zbd_logical_block_size); printf(" %llu physical blocks of %u B\n", (unsigned long long) info.zbd_physical_blocks, (unsigned int) info.zbd_physical_block_size); printf(" %.03F GB capacity\n", (double) (info.zbd_physical_blocks * info.zbd_physical_block_size) / 1000000000); printf("Target zone: Zone %d / %d, type 0x%x (%s), cond 0x%x (%s), need_reset %d, " "non_seq %d, LBA %llu, %llu sectors, wp %llu\n", zidx, nr_zones, zbc_zone_type(iozone), zbc_zone_type_str(zbc_zone_type(iozone)), zbc_zone_condition(iozone), zbc_zone_condition_str(zbc_zone_condition(iozone)), zbc_zone_need_reset(iozone), zbc_zone_non_seq(iozone), zbc_zone_start_lba(iozone), zbc_zone_length(iozone), zbc_zone_wp_lba(iozone)); /* Check alignment and get an I/O buffer */ if ( iosize % info.zbd_logical_block_size ) { fprintf(stderr, "Invalid I/O size %zu (must be aligned on %u)\n", iosize, (unsigned int) info.zbd_logical_block_size); ret = 1; goto out; } ret = posix_memalign((void **) &iobuf, sysconf(_SC_PAGESIZE), iosize); if ( ret != 0 ) { fprintf(stderr, "No memory for I/O buffer (%zu B)\n", iosize); ret = 1; goto out; } /* Open the file to write, if any */ if ( file ) { if ( strcmp(file, "-") == 0 ) { fd = fileno(stdout); printf("Writting target zone %d to standard output, %zu B I/Os\n", zidx, iosize); } else { fd = open(file, O_CREAT | O_TRUNC | O_LARGEFILE | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP); if ( fd < 0 ) { fprintf(stderr, "Open file \"%s\" failed %d (%s)\n", file, errno, strerror(errno)); ret = 1; goto out; } printf("Writting target zone %d to file \"%s\", %zu B I/Os\n", zidx, file, iosize); } } else if ( ! ionum ) { printf("Reading target zone %d, %zu B I/Os\n", zidx, iosize); } else { printf("Reading target zone %d, %llu I/Os of %zu B\n", zidx, ionum, iosize); } if ( zbc_zone_sequential_req(iozone) && (! zbc_zone_full(iozone)) ) { lba_max = zbc_zone_wp_lba(iozone) - zbc_zone_start_lba(iozone); } else { lba_max = zbc_zone_length(iozone); } lba_count = iosize / info.zbd_logical_block_size; elapsed = zbc_read_zone_usec(); while( (! zbc_read_zone_abort) && (lba_ofst < lba_max) ) { /* Read zone */ if ( (lba_ofst + lba_count) > lba_max ) { lba_count = lba_max - lba_ofst; } ret = zbc_pread(dev, iozone, iobuf, lba_count, lba_ofst); if ( ret <= 0 ) { fprintf(stderr, "zbc_pread failed %d (%s)\n", -ret, strerror(-ret)); ret = 1; break; } lba_count = ret; if ( file ) { /* Write file */ ret = write(fd, iobuf, lba_count * info.zbd_logical_block_size); if ( ret < 0 ) { fprintf(stderr, "Write file \"%s\" failed %d (%s)\n", file, errno, strerror(errno)); ret = 1; break; } } lba_ofst += lba_count; bcount += lba_count * info.zbd_logical_block_size; iocount++; ret = 0; /* If a number of IO was given as input then * lba_max = iozone + lba_ofst + ionum */ if ( (ionum > 0) && (iocount >= ionum) ) { break; } } elapsed = zbc_read_zone_usec() - elapsed; if ( elapsed ) { printf("Read %llu B (%llu I/Os) in %llu.%03llu sec\n", bcount, iocount, elapsed / 1000000, (elapsed % 1000000) / 1000); printf(" IOPS %llu\n", iocount * 1000000 / elapsed); brate = bcount * 1000000 / elapsed; printf(" BW %llu.%03llu MB/s\n", brate / 1000000, (brate % 1000000) / 1000); } else { printf("Read %llu B (%llu I/Os)\n", bcount, iocount); } out: if ( file && (fd > 0) ) { if ( fd != fileno(stdout) ) { close(fd); } if ( ret != 0 ) { unlink(file); } } if ( iobuf ) { free(iobuf); } if ( zones ) { free(zones); } zbc_close(dev); return( ret ); }