4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
27 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
30 * Copyright (c) 2013, Intel Corporation.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * lustre/utils/lr_reader.c
38 * Author: Nathan Rutman <nathan@clusterfs.com>
40 /* Safely read the last_rcvd file from a device */
44 #endif /* HAVE_CONFIG_H */
59 #include <sys/types.h>
61 #include <sys/mount.h>
66 #include <lustre_disk.h>
67 #include <lustre_ver.h>
70 static struct option const longopts[] = {
71 { "help", no_argument, 0, 'h' },
72 { "client", no_argument, 0, 'c' },
73 { "reply", no_argument, 0, 'r' },
77 /* Executes the command \a cmd and returns command status.
79 int run_command(char *cmd, size_t cmdsz)
81 char log[] = "/tmp/run_command_logXXXXXX";
84 if (strlen(cmd) + strlen(log) + 8 > cmdsz) {
85 fprintf(stderr, "Command buffer overflow: %.*s...\n",
93 strncat(cmd, " >", 2);
94 strncat(cmd, log, strlen(log));
96 strncat(cmd, " 2>&1", 5);
98 /* Can't use popen because we need the rv of the command */
103 fp = fopen(log, "r");
105 while (fgets(buf, sizeof(buf), fp) != NULL) {
118 void display_usage(void)
120 printf("Usage: %s [OPTIONS] devicename\n", progname);
121 printf("Read and print the last_rcvd file from a device\n");
122 printf("(safe for mounted devices)\n");
123 printf("\t-c, --client, display client information\n");
124 printf("\t-h, --help, display this help and exit\n");
125 printf("\t-r, --reply, display reply data information\n");
129 int main(int argc, char *const argv[])
131 char tmpdir[] = "/tmp/dirXXXXXX";
133 char filepnm[128] = "";
135 struct lr_server_data lsd;
143 while ((c = getopt_long(argc, argv, "chr", longopts, NULL)) != -1) {
163 /* Make a temporary directory to hold Lustre data files. */
164 if (!mkdtemp(tmpdir)) {
165 fprintf(stderr, "%s: Can't create temporary directory %s: %s\n",
166 progname, tmpdir, strerror(errno));
170 memset(cmd, 0, sizeof(cmd));
171 snprintf(cmd, sizeof(cmd),
172 "%s -c -R 'dump /%s %s/%s' %s",
173 DEBUGFS, LAST_RCVD, tmpdir, LAST_RCVD, dev);
175 ret = run_command(cmd, sizeof(cmd));
177 fprintf(stderr, "%s: Unable to dump %s file\n",
178 progname, LAST_RCVD);
182 snprintf(filepnm, 128, "%s/%s", tmpdir, LAST_RCVD);
183 filep = fopen(filepnm, "r");
185 fprintf(stderr, "%s: Unable to read old data\n",
192 /* read lr_server_data structure */
193 printf("%s:\n", LAST_RCVD);
194 ret = fread(&lsd, 1, sizeof(lsd), filep);
195 if (ret < sizeof(lsd)) {
196 fprintf(stderr, "%s: Short read (%d of %d)\n",
197 progname, ret, (int)sizeof(lsd));
198 ret = -ferror(filep);
203 /* swab structure fields of interest */
204 lsd.lsd_feature_compat = le32_to_cpu(lsd.lsd_feature_compat);
205 lsd.lsd_feature_incompat = le32_to_cpu(lsd.lsd_feature_incompat);
206 lsd.lsd_feature_rocompat = le32_to_cpu(lsd.lsd_feature_rocompat);
207 lsd.lsd_last_transno = le64_to_cpu(lsd.lsd_last_transno);
208 lsd.lsd_osd_index = le32_to_cpu(lsd.lsd_osd_index);
209 lsd.lsd_mount_count = le64_to_cpu(lsd.lsd_mount_count);
212 printf(" uuid: %.40s\n", lsd.lsd_uuid);
213 printf(" feature_compat: %#x\n", lsd.lsd_feature_compat);
214 printf(" feature_incompat: %#x\n", lsd.lsd_feature_incompat);
215 printf(" feature_rocompat: %#x\n", lsd.lsd_feature_rocompat);
216 printf(" last_transaction: %llu\n", lsd.lsd_last_transno);
217 printf(" target_index: %u\n", lsd.lsd_osd_index);
218 printf(" mount_count: %llu\n", lsd.lsd_mount_count);
220 /* read client information */
222 lsd.lsd_client_start = le32_to_cpu(lsd.lsd_client_start);
223 lsd.lsd_client_size = le16_to_cpu(lsd.lsd_client_size);
224 printf(" client_area_start: %u\n", lsd.lsd_client_start);
225 printf(" client_area_size: %hu\n", lsd.lsd_client_size);
227 /* seek to per-client data area */
228 ret = fseek(filep, lsd.lsd_client_start, SEEK_SET);
230 fprintf(stderr, "%s: seek failed. %s\n",
231 progname, strerror(errno));
236 /* walk throuh the per-client data area */
238 struct lsd_client_data lcd;
240 /* read a per-client data area */
241 ret = fread(&lcd, 1, sizeof(lcd), filep);
242 if (ret < sizeof(lcd)) {
245 fprintf(stderr, "%s: Short read (%d of %d)\n",
246 progname, ret, (int)sizeof(lcd));
247 ret = -ferror(filep);
251 if (lcd.lcd_uuid[0] == '\0')
254 /* swab structure fields */
255 lcd.lcd_last_transno =
256 le64_to_cpu(lcd.lcd_last_transno);
257 lcd.lcd_last_xid = le64_to_cpu(lcd.lcd_last_xid);
258 lcd.lcd_last_result = le32_to_cpu(lcd.lcd_last_result);
259 lcd.lcd_last_data = le32_to_cpu(lcd.lcd_last_data);
260 lcd.lcd_generation = le32_to_cpu(lcd.lcd_generation);
262 /* display per-client data area */
263 printf("\n %.40s:\n", lcd.lcd_uuid);
264 printf(" generation: %u\n", lcd.lcd_generation);
265 printf(" last_transaction: %llu\n",
266 lcd.lcd_last_transno);
267 printf(" last_xid: %llu\n", lcd.lcd_last_xid);
268 printf(" last_result: %u\n", lcd.lcd_last_result);
269 printf(" last_data: %u\n", lcd.lcd_last_data);
271 if (lcd.lcd_last_close_transno != 0 &&
272 lcd.lcd_last_close_xid != 0) {
273 lcd.lcd_last_close_transno =
274 le64_to_cpu(lcd.lcd_last_close_transno);
275 lcd.lcd_last_close_xid =
276 le64_to_cpu(lcd.lcd_last_close_xid);
277 lcd.lcd_last_close_result =
278 le32_to_cpu(lcd.lcd_last_close_result);
279 lcd.lcd_last_close_data =
280 le32_to_cpu(lcd.lcd_last_close_data);
281 printf(" last_close_transation: %llu\n",
282 lcd.lcd_last_close_transno);
283 printf(" last_close_xid: %llu\n",
284 lcd.lcd_last_close_xid);
285 printf(" last_close_result: %u\n",
286 lcd.lcd_last_close_result);
287 printf(" last_close_data: %u\n",
288 lcd.lcd_last_close_data);
295 /* read reply data information */
297 struct lsd_reply_header lrh;
298 struct lsd_reply_data lrd;
299 unsigned long long slot;
301 snprintf(cmd, sizeof(cmd),
302 "%s -c -R 'dump /%s %s/%s' %s",
303 DEBUGFS, REPLY_DATA, tmpdir, REPLY_DATA, dev);
305 ret = run_command(cmd, sizeof(cmd));
307 fprintf(stderr, "%s: Unable to dump %s file\n",
308 progname, REPLY_DATA);
312 snprintf(filepnm, sizeof(filepnm),
313 "%s/%s", tmpdir, REPLY_DATA);
314 filep = fopen(filepnm, "r");
316 fprintf(stderr, "%s: Unable to read reply data\n",
323 /* read reply_data header */
324 printf("\n%s:\n", REPLY_DATA);
325 ret = fread(&lrh, 1, sizeof(lrh), filep);
326 if (ret < sizeof(lrh)) {
327 fprintf(stderr, "%s: Short read (%d of %d)\n",
328 progname, ret, (int)sizeof(lrh));
329 ret = -ferror(filep);
335 lrh.lrh_magic = le32_to_cpu(lrh.lrh_magic);
336 lrh.lrh_header_size = le32_to_cpu(lrh.lrh_header_size);
337 lrh.lrh_reply_size = le32_to_cpu(lrh.lrh_reply_size);
338 if (lrh.lrh_magic != LRH_MAGIC) {
339 fprintf(stderr, "%s: invalid %s header: "
340 "lrh_magic=%08x expected %08x\n",
341 progname, REPLY_DATA, lrh.lrh_magic, LRH_MAGIC);
344 if (lrh.lrh_header_size != sizeof(struct lsd_reply_header)) {
345 fprintf(stderr, "%s: invalid %s header: "
346 "lrh_header_size=%08x expected %08x\n",
347 progname, REPLY_DATA, lrh.lrh_header_size,
348 (unsigned int)sizeof(struct lsd_reply_header));
351 if (lrh.lrh_reply_size != sizeof(struct lsd_reply_data)) {
352 fprintf(stderr, "%s: invalid %s header: "
353 "lrh_reply_size=%08x expected %08x\n",
354 progname, REPLY_DATA, lrh.lrh_reply_size,
355 (unsigned int)sizeof(struct lsd_reply_data));
359 /* walk throuh the reply data */
360 for (slot = 0; ; slot++) {
361 /* read a reply data */
362 ret = fread(&lrd, 1, sizeof(lrd), filep);
363 if (ret < sizeof(lrd)) {
366 fprintf(stderr, "%s: Short read (%d of %d)\n",
367 progname, ret, (int)sizeof(lrd));
368 ret = -ferror(filep);
372 /* display reply data */
373 lrd.lrd_transno = le64_to_cpu(lrd.lrd_transno);
374 lrd.lrd_xid = le64_to_cpu(lrd.lrd_xid);
375 lrd.lrd_data = le64_to_cpu(lrd.lrd_data);
376 lrd.lrd_result = le32_to_cpu(lrd.lrd_result);
377 lrd.lrd_client_gen = le32_to_cpu(lrd.lrd_client_gen);
379 printf(" %lld:\n", slot);
380 printf(" client_generation: %u\n",
382 printf(" last_transaction: %llu\n", lrd.lrd_transno);
383 printf(" last_xid: %llu\n", lrd.lrd_xid);
384 printf(" last_result: %u\n", lrd.lrd_result);
385 printf(" last_data: %llu\n\n", lrd.lrd_data);