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.
31 * This file is part of Lustre, http://www.lustre.org/
32 * Lustre is a trademark of Sun Microsystems, Inc.
34 * lustre/utils/lr_reader.c
36 * Author: Nathan Rutman <nathan@clusterfs.com>
38 /* Safely read the last_rcvd file from a device */
42 #endif /* HAVE_CONFIG_H */
54 #include <sys/types.h>
56 #include <sys/mount.h>
61 #include <lustre_disk.h>
62 #include <lustre_ver.h>
64 int run_command(char *cmd)
66 char log[] = "/tmp/mkfs_logXXXXXX";
70 if ((fd = mkstemp(log)) >= 0) {
77 /* Can't use popen because we need the rv of the command */
84 while (fgets(buf, sizeof(buf), fp) != NULL) {
98 int main(int argc, char *const argv[])
100 char tmpdir[] = "/tmp/dirXXXXXX";
103 char *progname, *dev;
104 struct lr_server_data lsd;
108 if ((argc < 2) || (argv[argc - 1][0] == '-')) {
109 printf("Usage: %s devicename\n", argv[0]);
110 printf("Read and print the last_rcvd file from a device\n");
111 printf("(safe for mounted devices)\n");
116 dev = argv[argc - 1];
118 /* Make a temporary directory to hold Lustre data files. */
119 if (!mkdtemp(tmpdir)) {
120 fprintf(stderr, "%s: Can't create temporary directory %s: %s\n",
121 progname, tmpdir, strerror(errno));
125 memset(cmd, 0, sizeof(cmd));
127 "%s -c -R 'dump /%s %s/%s' %s",
128 DEBUGFS, LAST_RCVD, tmpdir, LAST_RCVD, dev);
130 ret = run_command(cmd);
132 fprintf(stderr, "%s: Unable to dump %s file\n",
133 progname, LAST_RCVD);
137 sprintf(filepnm, "%s/%s", tmpdir, LAST_RCVD);
138 filep = fopen(filepnm, "r");
140 fprintf(stderr, "%s: Unable to read old data\n",
146 printf("Reading %s\n", LAST_RCVD);
147 ret = fread(&lsd, 1, sizeof(lsd), filep);
148 if (ret < sizeof(lsd)) {
149 fprintf(stderr, "%s: Short read (%d of %d)\n",
150 progname, ret, (int)sizeof(lsd));
151 ret = -ferror(filep);
157 __u8 lsd_uuid[40]; /* server UUID */
158 __u64 lsd_last_transno; /* last completed transaction ID */
159 __u64 lsd_compat14; /* reserved - compat with old last_rcvd */
160 __u64 lsd_mount_count; /* incarnation number */
161 __u32 lsd_feature_compat; /* compatible feature flags */
162 __u32 lsd_feature_rocompat;/* read-only compatible feature flags */
163 __u32 lsd_feature_incompat;/* incompatible feature flags */
164 __u32 lsd_server_size; /* size of server data area */
165 __u32 lsd_client_start; /* start of per-client data area */
166 __u16 lsd_client_size; /* size of per-client data area */
167 __u16 lsd_subdir_count; /* number of subdirectories for objects */
168 __u64 lsd_catalog_oid; /* recovery catalog object id */
169 __u32 lsd_catalog_ogen; /* recovery catalog inode generation */
170 __u8 lsd_peeruuid[40]; /* UUID of MDS associated with this OST */
171 __u32 lsd_ost_index; /* index number of OST in LOV */
172 __u32 lsd_mdt_index; /* index number of MDT in LMV */
173 __u8 lsd_padding[LR_SERVER_SIZE - 148];
176 printf("UUID %s\n", lsd.lsd_uuid);
177 printf("Feature compat=%#x\n", lsd.lsd_feature_compat);
178 printf("Feature incompat=%#x\n", lsd.lsd_feature_incompat);
179 printf("Feature rocompat=%#x\n", lsd.lsd_feature_rocompat);
180 printf("Last transaction %llu\n", (long long)lsd.lsd_last_transno);
181 printf("ost index %u\n", lsd.lsd_ost_index);
182 printf("mdt index %u\n", lsd.lsd_mdt_index);
184 if ((lsd.lsd_feature_compat & OBD_COMPAT_OST) ||
185 (lsd.lsd_feature_incompat & OBD_INCOMPAT_OST)) {
186 printf("OST, index %d\n", lsd.lsd_ost_index);
187 } else if ((lsd.lsd_feature_compat & OBD_COMPAT_MDT) ||
188 (lsd.lsd_feature_incompat & OBD_INCOMPAT_MDT)) {
189 /* We must co-locate so mgs can see old logs.
190 If user doesn't want this, they can copy the old
191 logs manually and re-tunefs. */
192 printf("MDS, index %d\n", lsd.lsd_mdt_index);
194 /* If neither is set, we're pre-1.4.6, make a guess. */
195 /* Construct debugfs command line. */
196 memset(cmd, 0, sizeof(cmd));
198 "%s -c -R 'rdump /%s %s' %s",
199 DEBUGFS, MDT_LOGS_DIR, tmpdir, dev);
203 sprintf(filepnm, "%s/%s", tmpdir, MDT_LOGS_DIR);
204 if (lsd.lsd_ost_index > 0) {
205 printf("non-flagged OST, index %d\n",
208 /* If there's a LOGS dir, it's an MDT */
209 if ((ret = access(filepnm, F_OK)) == 0) {
210 /* Old MDT's are always index 0
212 printf("non-flagged MDS, index 0\n");
214 printf("non-flagged OST, index unknown\n");
223 memset(cmd, 0, sizeof(cmd));
224 sprintf(cmd, "rm -rf %s", tmpdir);