int dz_get_zones(void) { unsigned int nr_zones; int ret; ret = zbc_report_nr_zones(dz.dev, 0, ZBC_RO_ALL, &nr_zones); if ( ret != 0 ) { return( ret ); } if ( dz.nr_zones && (dz.nr_zones != nr_zones) ) { /* Zone list changed: clean it */ free(dz.zones); dz.zones = NULL; dz.nr_zones = 0; } if ( ! dz.nr_zones ) { printf("Device \"%s\": %llu sectors of %u B, %d zones\n", dz.filename, (unsigned long long) dz.info.zbd_physical_blocks, (unsigned int) dz.info.zbd_physical_block_size, nr_zones); } /* Get/refresh zone list */ ret = zbc_list_zones(dz.dev, 0, ZBC_RO_ALL, &dz.zones, &dz.nr_zones); if ( ret != 0 ) { ret = errno; fprintf(stderr, "zbc_list_zones failed %d (%s)\n", errno, strerror(errno)); if ( dz.zones ) { free(dz.zones); dz.zones = NULL; dz.nr_zones = 0; } goto out; } out: return( ret ); }
/** * zbc_list_zones - report zones for a ZBC device * @dev: (IN) ZBC device handle to report on * @start_lba: (IN) start LBA for the first zone to reported * @ro: (IN) Reporting options * @zones: (OUT) pointer for reported zones * @nr_zones: (OUT) number of returned zones * * Reports the number and details of available zones. The @zones * parameter is used to return an array of zones which is allocated using * malloc(3) internally and needs to be freed using free(3). The number * of zones in @zones is returned in @nr_zones. * * Returns -EIO if an error happened when communicating to the device. * Returns -ENOMEM if memory could not be allocated for @zones. */ int zbc_list_zones(struct zbc_device *dev, uint64_t start_lba, enum zbc_reporting_options ro, struct zbc_zone **pzones, unsigned int *pnr_zones) { zbc_zone_t *zones = NULL; unsigned int nr_zones; int ret; /* Get total number of zones */ ret = zbc_report_nr_zones(dev, start_lba, ro, &nr_zones); if ( ret < 0 ) { return( ret ); } zbc_debug("Device %s: %d zones\n", dev->zbd_filename, nr_zones); /* Allocate zone array */ zones = (zbc_zone_t *) malloc(sizeof(zbc_zone_t) * nr_zones); if ( ! zones ) { zbc_error("No memory\n"); return( -ENOMEM ); } memset(zones, 0, sizeof(zbc_zone_t) * nr_zones); /* Get zones info */ ret = zbc_report_zones(dev, start_lba, ro, zones, &nr_zones); if ( ret != 0 ) { zbc_error("zbc_report_zones failed\n"); free(zones); } else { *pzones = zones; *pnr_zones = nr_zones; } 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; 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; 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 ); }