Whamcloud - gitweb
5a2b11ff7e0cc82bb4620637a58fa3c018aa7c13
[fs/lustre-release.git] / lustre / utils / lr_reader.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright  2008 Sun Microsystems, Inc. All rights reserved
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/utils/lr_reader.c
37  *
38  * Author: Nathan Rutman <nathan@clusterfs.com>
39  */
40  /* Safely read the last_rcvd file from a device */
41
42 #if HAVE_CONFIG_H
43 #  include "config.h"
44 #endif /* HAVE_CONFIG_H */
45
46 #ifndef _GNU_SOURCE
47 #define _GNU_SOURCE
48 #endif
49 #include <stdlib.h>
50 #include <stdio.h>
51 #include <unistd.h>
52 #include <fcntl.h>
53 #include <stdarg.h>
54 #include <mntent.h>
55
56 #include <sys/types.h>
57 #include <sys/stat.h>
58 #include <sys/mount.h>
59
60 #include <string.h>
61 #include <getopt.h>
62
63 #include <lustre_disk.h>
64 #include <lustre_ver.h>
65
66 int run_command(char *cmd)
67 {
68         char log[] = "/tmp/mkfs_logXXXXXX";
69         int fd, rc;
70         
71         
72         if ((fd = mkstemp(log)) >= 0) {
73                 close(fd);
74                 strcat(cmd, " >");
75                 strcat(cmd, log);
76         }
77         strcat(cmd, " 2>&1");
78
79         /* Can't use popen because we need the rv of the command */
80         rc = system(cmd);
81         if (rc && fd >= 0) {
82                 char buf[128];
83                 FILE *fp;
84                 fp = fopen(log, "r");
85                 if (fp) {
86                         while (fgets(buf, sizeof(buf), fp) != NULL) {
87                                 if (rc) 
88                                         printf("   %s", buf);
89                         }
90                         fclose(fp);
91                 }
92         }
93         if (fd >= 0) 
94                 remove(log);
95         return rc;
96 }                                                       
97
98
99
100 int main(int argc, char *const argv[])
101 {
102         char tmpdir[] = "/tmp/dirXXXXXX";
103         char cmd[128];
104         char filepnm[128];
105         char *progname, *dev;
106         struct lr_server_data lsd;
107         FILE *filep;
108         int ret;
109
110         if ((argc < 2) || (argv[argc - 1][0] == '-')) {
111                 printf("Usage: %s devicename\n", argv[0]);
112                 printf("Read and print the last_rcvd file from a device\n");
113                 printf("(safe for mounted devices)\n");
114                 return EINVAL;
115         }
116
117         progname = argv[0];
118         dev = argv[argc - 1];
119
120         /* Make a temporary directory to hold Lustre data files. */
121         if (!mkdtemp(tmpdir)) {
122                 fprintf(stderr, "%s: Can't create temporary directory %s: %s\n",
123                         progname, tmpdir, strerror(errno));
124                 return errno;
125         }
126
127         memset(cmd, 0, sizeof(cmd));
128         sprintf(cmd,
129                 "%s -c -R 'dump /%s %s/%s' %s",
130                 DEBUGFS, LAST_RCVD, tmpdir, LAST_RCVD, dev);
131
132         ret = run_command(cmd);
133         if (ret) {
134                 fprintf(stderr, "%s: Unable to dump %s file\n",
135                         progname, LAST_RCVD);
136                 goto out_rmdir;
137         }
138
139         sprintf(filepnm, "%s/%s", tmpdir, LAST_RCVD);
140         filep = fopen(filepnm, "r");
141         if (!filep) {
142                 fprintf(stderr, "%s: Unable to read old data\n",
143                         progname);
144                 ret = -errno;
145                 goto out_rmdir;
146         }
147
148         printf("Reading %s\n", LAST_RCVD);
149         ret = fread(&lsd, 1, sizeof(lsd), filep);
150         if (ret < sizeof(lsd)) {
151                 fprintf(stderr, "%s: Short read (%d of %d)\n",
152                         progname, ret, (int)sizeof(lsd));
153                 ret = -ferror(filep);
154                 if (ret) 
155                         goto out_close;
156         }
157
158         #if 0
159         __u8  lsd_uuid[40];        /* server UUID */
160         __u64 lsd_last_transno;    /* last completed transaction ID */
161         __u64 lsd_compat14;        /* reserved - compat with old last_rcvd */
162         __u64 lsd_mount_count;     /* incarnation number */
163         __u32 lsd_feature_compat;  /* compatible feature flags */
164         __u32 lsd_feature_rocompat;/* read-only compatible feature flags */
165         __u32 lsd_feature_incompat;/* incompatible feature flags */
166         __u32 lsd_server_size;     /* size of server data area */
167         __u32 lsd_client_start;    /* start of per-client data area */
168         __u16 lsd_client_size;     /* size of per-client data area */
169         __u16 lsd_subdir_count;    /* number of subdirectories for objects */
170         __u64 lsd_catalog_oid;     /* recovery catalog object id */
171         __u32 lsd_catalog_ogen;    /* recovery catalog inode generation */
172         __u8  lsd_peeruuid[40];    /* UUID of MDS associated with this OST */
173         __u32 lsd_ost_index;       /* index number of OST in LOV */
174         __u32 lsd_mdt_index;       /* index number of MDT in LMV */
175         __u8  lsd_padding[LR_SERVER_SIZE - 148];
176         #endif
177
178         printf("UUID %s\n", lsd.lsd_uuid);
179         printf("Feature compat=%#x\n", lsd.lsd_feature_compat);
180         printf("Feature incompat=%#x\n", lsd.lsd_feature_incompat);
181         printf("Feature rocompat=%#x\n", lsd.lsd_feature_rocompat);
182         printf("Last transaction %llu\n", (long long)lsd.lsd_last_transno);
183         printf("ost index %u\n", lsd.lsd_ost_index);
184         printf("mdt index %u\n", lsd.lsd_mdt_index);
185
186         if ((lsd.lsd_feature_compat & OBD_COMPAT_OST) ||
187             (lsd.lsd_feature_incompat & OBD_INCOMPAT_OST)) {
188                 printf("OST, index %d\n", lsd.lsd_ost_index);
189         } else if ((lsd.lsd_feature_compat & OBD_COMPAT_MDT) ||
190                    (lsd.lsd_feature_incompat & OBD_INCOMPAT_MDT)) {
191                 /* We must co-locate so mgs can see old logs.
192                    If user doesn't want this, they can copy the old
193                    logs manually and re-tunefs. */
194                 printf("MDS, index %d\n", lsd.lsd_mdt_index);
195         } else  {
196                 /* If neither is set, we're pre-1.4.6, make a guess. */
197                 /* Construct debugfs command line. */
198                 memset(cmd, 0, sizeof(cmd));
199                 sprintf(cmd,
200                         "%s -c -R 'rdump /%s %s' %s",
201                         DEBUGFS, MDT_LOGS_DIR, tmpdir, dev);
202
203                 run_command(cmd);
204
205                 sprintf(filepnm, "%s/%s", tmpdir, MDT_LOGS_DIR);
206                 if (lsd.lsd_ost_index > 0) {
207                         printf("non-flagged OST, index %d\n", 
208                                lsd.lsd_ost_index);
209                 } else {
210                         /* If there's a LOGS dir, it's an MDT */
211                         if ((ret = access(filepnm, F_OK)) == 0) {
212                                 /* Old MDT's are always index 0 
213                                    (pre CMD) */
214                                 printf("non-flagged MDS, index 0\n");
215                         } else {
216                                 printf("non-flagged OST, index unknown\n");
217                         }
218                 }
219         }
220         
221 out_close:        
222         fclose(filep);
223
224 out_rmdir:
225         memset(cmd, 0, sizeof(cmd));
226         sprintf(cmd, "rm -rf %s", tmpdir);
227         run_command(cmd);
228         return ret;
229 }