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