+ /* read client information */
+ if (opt_client) {
+ lsd.lsd_client_start = __le32_to_cpu(lsd.lsd_client_start);
+ lsd.lsd_client_size = __le16_to_cpu(lsd.lsd_client_size);
+ printf(" client_area_start: %u\n", lsd.lsd_client_start);
+ printf(" client_area_size: %hu\n", lsd.lsd_client_size);
+
+ /* seek to per-client data area */
+ ret = fseek(filep, lsd.lsd_client_start, SEEK_SET);
+ if (ret) {
+ fprintf(stderr, "%s: seek failed. %s\n",
+ progname, strerror(errno));
+ ret = errno;
+ goto out_close;
+ }
+
+ /* walk throuh the per-client data area */
+ while (true) {
+ struct lsd_client_data lcd;
+
+ /* read a per-client data area */
+ ret = fread(&lcd, 1, sizeof(lcd), filep);
+ if (ret < sizeof(lcd)) {
+ if (feof(filep))
+ break;
+ fprintf(stderr, "%s: Short read (%d of %d)\n",
+ progname, ret, (int)sizeof(lcd));
+ ret = -ferror(filep);
+ goto out_close;
+ }
+
+ if (lcd.lcd_uuid[0] == '\0')
+ continue;
+
+ /* swab structure fields */
+ lcd.lcd_last_transno =
+ __le64_to_cpu(lcd.lcd_last_transno);
+ lcd.lcd_last_xid = __le64_to_cpu(lcd.lcd_last_xid);
+ lcd.lcd_last_result = __le32_to_cpu(lcd.lcd_last_result);
+ lcd.lcd_last_data = __le32_to_cpu(lcd.lcd_last_data);
+ lcd.lcd_generation = __le32_to_cpu(lcd.lcd_generation);
+
+ /* display per-client data area */
+ printf("\n %.40s:\n", lcd.lcd_uuid);
+ printf(" generation: %u\n", lcd.lcd_generation);
+ printf(" last_transaction: %llu\n",
+ lcd.lcd_last_transno);
+ printf(" last_xid: %llu\n", lcd.lcd_last_xid);
+ printf(" last_result: %u\n", lcd.lcd_last_result);
+ printf(" last_data: %u\n", lcd.lcd_last_data);
+
+ if (lcd.lcd_last_close_transno != 0 &&
+ lcd.lcd_last_close_xid != 0) {
+ lcd.lcd_last_close_transno =
+ __le64_to_cpu(lcd.lcd_last_close_transno);
+ lcd.lcd_last_close_xid =
+ __le64_to_cpu(lcd.lcd_last_close_xid);
+ lcd.lcd_last_close_result =
+ __le32_to_cpu(lcd.lcd_last_close_result);
+ lcd.lcd_last_close_data =
+ __le32_to_cpu(lcd.lcd_last_close_data);
+ printf(" last_close_transation: %llu\n",
+ lcd.lcd_last_close_transno);
+ printf(" last_close_xid: %llu\n",
+ lcd.lcd_last_close_xid);
+ printf(" last_close_result: %u\n",
+ lcd.lcd_last_close_result);
+ printf(" last_close_data: %u\n",
+ lcd.lcd_last_close_data);
+ }
+ }
+ }
+ fclose(filep);
+ filep = NULL;
+
+ /* read reply data information */
+ if (opt_reply) {
+ struct lsd_reply_header lrh;
+ struct lsd_reply_data lrd;
+ unsigned long long slot;
+
+ snprintf(cmd, sizeof(cmd),
+ "%s -c -R 'dump /%s %s/%s' %s",
+ DEBUGFS, REPLY_DATA, tmpdir, REPLY_DATA, dev);
+
+ ret = run_command(cmd, sizeof(cmd));
+ if (ret) {
+ fprintf(stderr, "%s: Unable to dump %s file\n",
+ progname, REPLY_DATA);
+ goto out_rmdir;
+ }
+
+ snprintf(filepnm, sizeof(filepnm),
+ "%s/%s", tmpdir, REPLY_DATA);
+ filep = fopen(filepnm, "r");
+ if (!filep) {
+ fprintf(stderr, "%s: Unable to read reply data\n",
+ progname);
+ ret = -errno;
+ goto out_rmdir;
+ }
+ unlink(filepnm);
+
+ /* read reply_data header */
+ printf("\n%s:\n", REPLY_DATA);
+ ret = fread(&lrh, 1, sizeof(lrh), filep);
+ if (ret < sizeof(lrh)) {
+ fprintf(stderr, "%s: Short read (%d of %d)\n",
+ progname, ret, (int)sizeof(lrh));
+ ret = -ferror(filep);
+ if (ret)
+ goto out_close;
+ }
+
+ /* check header */
+ lrh.lrh_magic = __le32_to_cpu(lrh.lrh_magic);
+ lrh.lrh_header_size = __le32_to_cpu(lrh.lrh_header_size);
+ lrh.lrh_reply_size = __le32_to_cpu(lrh.lrh_reply_size);
+ if (lrh.lrh_magic != LRH_MAGIC) {
+ fprintf(stderr, "%s: invalid %s header: "
+ "lrh_magic=%08x expected %08x\n",
+ progname, REPLY_DATA, lrh.lrh_magic, LRH_MAGIC);
+ goto out_close;
+ }
+ if (lrh.lrh_header_size != sizeof(struct lsd_reply_header)) {
+ fprintf(stderr, "%s: invalid %s header: "
+ "lrh_header_size=%08x expected %08x\n",
+ progname, REPLY_DATA, lrh.lrh_header_size,
+ (unsigned int)sizeof(struct lsd_reply_header));
+ goto out_close;
+ }
+ if (lrh.lrh_reply_size != sizeof(struct lsd_reply_data)) {
+ fprintf(stderr, "%s: invalid %s header: "
+ "lrh_reply_size=%08x expected %08x\n",
+ progname, REPLY_DATA, lrh.lrh_reply_size,
+ (unsigned int)sizeof(struct lsd_reply_data));
+ goto out_close;
+ }
+
+ /* walk throuh the reply data */
+ for (slot = 0; ; slot++) {
+ /* read a reply data */
+ ret = fread(&lrd, 1, sizeof(lrd), filep);
+ if (ret < sizeof(lrd)) {
+ if (feof(filep))
+ break;
+ fprintf(stderr, "%s: Short read (%d of %d)\n",
+ progname, ret, (int)sizeof(lrd));
+ ret = -ferror(filep);
+ goto out_close;
+ }
+
+ /* display reply data */
+ lrd.lrd_transno = __le64_to_cpu(lrd.lrd_transno);
+ lrd.lrd_xid = __le64_to_cpu(lrd.lrd_xid);
+ lrd.lrd_data = __le64_to_cpu(lrd.lrd_data);
+ lrd.lrd_result = __le32_to_cpu(lrd.lrd_result);
+ lrd.lrd_client_gen = __le32_to_cpu(lrd.lrd_client_gen);
+
+ printf(" %lld:\n", slot);
+ printf(" client_generation: %u\n",
+ lrd.lrd_client_gen);
+ printf(" last_transaction: %llu\n", lrd.lrd_transno);
+ printf(" last_xid: %llu\n", lrd.lrd_xid);
+ printf(" last_result: %u\n", lrd.lrd_result);
+ printf(" last_data: %llu\n\n", lrd.lrd_data);
+ }
+ }
+
+out_close:
+ if (filep != NULL)
+ fclose(filep);
+
+out_rmdir:
+ rmdir(tmpdir);
+ return ret;
+}