Whamcloud - gitweb
LU-1222 ldlm: Fix the race in AST sender vs multiple arriving RPCs
[fs/lustre-release.git] / lustre / utils / llog_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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
30  * Use is subject to license terms.
31  *
32  * Copyright (c) 2011, Whamcloud, Inc.
33  */
34 /*
35  * This file is part of Lustre, http://www.lustre.org/
36  * Lustre is a trademark of Sun Microsystems, Inc.
37  */
38  /* Interpret configuration llogs */
39
40
41 #include <stdio.h>
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #include <fcntl.h>
45
46 #include <time.h>
47 #include <liblustre.h>
48 #include <lustre/lustre_idl.h>
49
50 int llog_pack_buffer(int fd, struct llog_log_hdr **llog_buf,
51                      struct llog_rec_hdr ***recs, int *recs_number);
52
53 void print_llog_header(struct llog_log_hdr *llog_buf);
54 void print_records(struct llog_rec_hdr **recs_buf,int rec_number);
55 void llog_unpack_buffer(int fd, struct llog_log_hdr *llog_buf,
56                         struct llog_rec_hdr **recs_buf);
57
58 #define CANCELLED 0x678
59
60 #define PTL_CMD_BASE 100
61 char* portals_command[17]=
62 {
63         "REGISTER_PEER_FD",
64         "CLOSE_CONNECTION",
65         "REGISTER_MYNID",
66         "PUSH_CONNECTION",
67         "GET_CONN",
68         "DEL_PEER",
69         "ADD_PEER",
70         "GET_PEER",
71         "GET_TXDESC",
72         "ADD_ROUTE",
73         "DEL_ROUTE",
74         "GET_ROUTE",
75         "NOTIFY_ROUTER",
76         "ADD_INTERFACE",
77         "DEL_INTERFACE",
78         "GET_INTERFACE",
79         ""
80 };
81
82 int main(int argc, char **argv)
83 {
84         int rc = 0;
85         int fd, rec_number;
86         struct llog_log_hdr *llog_buf = NULL;
87         struct llog_rec_hdr **recs_buf = NULL;
88
89         setlinebuf(stdout);
90
91         if(argc != 2 ){
92                 printf("Usage: llog_reader filename\n");
93                 return -1;
94         }
95
96         fd = open(argv[1],O_RDONLY);
97         if (fd < 0){
98                 printf("Could not open the file %s\n", argv[1]);
99                 goto out;
100         }
101         rc = llog_pack_buffer(fd, &llog_buf, &recs_buf, &rec_number);
102         if (rc < 0) {
103                 printf("Could not pack buffer; rc=%d\n", rc);
104                 goto out_fd;
105         }
106
107         print_llog_header(llog_buf);
108         print_records(recs_buf,rec_number);
109         llog_unpack_buffer(fd,llog_buf,recs_buf);
110 out_fd:
111         close(fd);
112 out:
113         return rc;
114 }
115
116
117
118 int llog_pack_buffer(int fd, struct llog_log_hdr **llog,
119                      struct llog_rec_hdr ***recs,
120                      int *recs_number)
121 {
122         int rc = 0, recs_num,rd;
123         off_t file_size;
124         struct stat st;
125         char *file_buf=NULL, *recs_buf=NULL;
126         struct llog_rec_hdr **recs_pr=NULL;
127         char *ptr=NULL;
128         int i;
129
130         rc = fstat(fd,&st);
131         if (rc < 0){
132                 printf("Get file stat error.\n");
133                 goto out;
134         }
135         file_size = st.st_size;
136
137         file_buf = malloc(file_size);
138         if (file_buf == NULL){
139                 printf("Memory Alloc for file_buf error.\n");
140                 rc = -ENOMEM;
141                 goto out;
142         }
143         *llog = (struct llog_log_hdr*)file_buf;
144
145         rd = read(fd,file_buf,file_size);
146         if (rd < file_size){
147                 printf("Read file error.\n");
148                 rc = -EIO; /*FIXME*/
149                 goto clear_file_buf;
150         }
151
152         /* the llog header not countable here.*/
153         recs_num = le32_to_cpu((*llog)->llh_count)-1;
154
155         recs_buf = malloc(recs_num * sizeof(struct llog_rec_hdr *));
156         if (recs_buf == NULL){
157                 printf("Memory Alloc for recs_buf error.\n");
158                 rc = -ENOMEM;
159                 goto clear_file_buf;
160         }
161         recs_pr = (struct llog_rec_hdr **)recs_buf;
162
163         ptr = file_buf + le32_to_cpu((*llog)->llh_hdr.lrh_len);
164         i = 0;
165
166         while (i < recs_num){
167                 struct llog_rec_hdr *cur_rec = (struct llog_rec_hdr*)ptr;
168                 int idx = le32_to_cpu(cur_rec->lrh_index);
169                 recs_pr[i] = cur_rec;
170
171                 if (ext2_test_bit(idx, (*llog)->llh_bitmap)) {
172                         if (le32_to_cpu(cur_rec->lrh_type) != OBD_CFG_REC)
173                                 printf("rec #%d type=%x len=%u\n", idx,
174                                        cur_rec->lrh_type, cur_rec->lrh_len);
175                 } else {
176                         printf("Bit %d of %d not set\n", idx, recs_num);
177                         cur_rec->lrh_padding = CANCELLED;
178                         /* The header counts only set records */
179                         i--;
180                 }
181
182                 ptr += le32_to_cpu(cur_rec->lrh_len);
183                 if ((ptr - file_buf) > file_size) {
184                         printf("The log is corrupt (too big at %d)\n", i);
185                         rc = -EINVAL;
186                         goto clear_recs_buf;
187                 }
188                 i++;
189         }
190
191         *recs = recs_pr;
192         *recs_number = recs_num;
193
194 out:
195         return rc;
196
197 clear_recs_buf:
198         free(recs_buf);
199
200 clear_file_buf:
201         free(file_buf);
202
203         *llog=NULL;
204         goto out;
205 }
206
207 void llog_unpack_buffer(int fd, struct llog_log_hdr *llog_buf,
208                         struct llog_rec_hdr **recs_buf)
209 {
210         free(llog_buf);
211         free(recs_buf);
212         return;
213 }
214
215 void print_llog_header(struct llog_log_hdr *llog_buf)
216 {
217         time_t t;
218
219         printf("Header size : %u\n",
220                le32_to_cpu(llog_buf->llh_hdr.lrh_len));
221
222         t = le64_to_cpu(llog_buf->llh_timestamp);
223         printf("Time : %s", ctime(&t));
224
225         printf("Number of records: %u\n",
226                le32_to_cpu(llog_buf->llh_count)-1);
227
228         printf("Target uuid : %s \n",
229                (char *)(&llog_buf->llh_tgtuuid));
230
231         /* Add the other info you want to view here */
232
233         printf("-----------------------\n");
234         return;
235 }
236
237 static void print_1_cfg(struct lustre_cfg *lcfg)
238 {
239         int i;
240
241         if (lcfg->lcfg_nid)
242                 printf("nid=%s("LPX64")  ", libcfs_nid2str(lcfg->lcfg_nid),
243                        lcfg->lcfg_nid);
244         if (lcfg->lcfg_nal)
245                 printf("nal=%d ", lcfg->lcfg_nal);
246         for (i = 0; i <  lcfg->lcfg_bufcount; i++)
247                 printf("%d:%.*s  ", i, lcfg->lcfg_buflens[i],
248                        (char*)lustre_cfg_buf(lcfg, i));
249         return;
250 }
251
252
253 static void print_setup_cfg(struct lustre_cfg *lcfg)
254 {
255         struct lov_desc *desc;
256
257         if ((lcfg->lcfg_bufcount == 2) &&
258             (lcfg->lcfg_buflens[1] == sizeof(*desc))) {
259                 printf("lov_setup ");
260                 printf("0:%s  ", lustre_cfg_string(lcfg, 0));
261                 printf("1:(struct lov_desc)\n");
262                 desc = (struct lov_desc*)(lustre_cfg_string(lcfg, 1));
263                 printf("\t\tuuid=%s  ", (char*)desc->ld_uuid.uuid);
264                 printf("stripe:cnt=%u ", desc->ld_default_stripe_count);
265                 printf("size="LPU64" ", desc->ld_default_stripe_size);
266                 printf("offset="LPU64" ", desc->ld_default_stripe_offset);
267                 printf("pattern=%#x", desc->ld_pattern);
268         } else {
269                 printf("setup     ");
270                 print_1_cfg(lcfg);
271         }
272         
273         return;
274 }
275
276 void print_lustre_cfg(struct lustre_cfg *lcfg, int *skip)
277 {
278         enum lcfg_command_type cmd = le32_to_cpu(lcfg->lcfg_command);
279
280         if (*skip > 0)
281                 printf("SKIP ");
282
283         switch(cmd){
284         case(LCFG_ATTACH):{
285                 printf("attach    ");
286                 print_1_cfg(lcfg);
287                 break;
288         }
289         case(LCFG_SETUP):{
290                 print_setup_cfg(lcfg);
291                 break;
292         }
293         case(LCFG_DETACH):{
294                 printf("detach    ");
295                 print_1_cfg(lcfg);
296                 break;
297         }
298         case(LCFG_CLEANUP):{
299                 printf("cleanup   ");
300                 print_1_cfg(lcfg);
301                 break;
302         }
303         case(LCFG_ADD_UUID):{
304                 printf("add_uuid  ");
305                 print_1_cfg(lcfg);
306                 break;
307         }
308         case(LCFG_DEL_UUID):{
309                 printf("del_uuid  ");
310                 print_1_cfg(lcfg);
311                 break;
312         }
313         case(LCFG_ADD_CONN):{
314                 printf("add_conn  ");
315                 print_1_cfg(lcfg);
316                 break;
317         }
318         case(LCFG_DEL_CONN):{
319                 printf("del_conn  ");
320                 print_1_cfg(lcfg);
321                 break;
322         }
323         case(LCFG_LOV_ADD_OBD):{
324                 printf("lov_modify_tgts add ");
325                 print_1_cfg(lcfg);
326                 break;
327         }
328         case(LCFG_LOV_DEL_OBD):{
329                 printf("lov_modify_tgts del ");
330                 print_1_cfg(lcfg);
331                 break;
332         }
333         case(LCFG_ADD_MDC):{
334                 printf("modify_mdc_tgts add ");
335                 print_1_cfg(lcfg);
336                 break;
337         }
338         case(LCFG_DEL_MDC):{
339                 printf("modify_mdc_tgts del ");
340                 print_1_cfg(lcfg);
341                 break;
342         }
343         case(LCFG_MOUNTOPT):{
344                 printf("mount_option ");
345                 print_1_cfg(lcfg);
346                 break;
347         }
348         case(LCFG_DEL_MOUNTOPT):{
349                 printf("del_mount_option ");
350                 print_1_cfg(lcfg);
351                 break;
352         }
353         case(LCFG_SET_TIMEOUT):{
354                 printf("set_timeout=%d ", lcfg->lcfg_num);
355                 break;
356         }
357         case(LCFG_SET_LDLM_TIMEOUT):{
358                 printf("set_ldlm_timeout=%d ", lcfg->lcfg_num);
359                 break;
360         }
361         case(LCFG_SET_UPCALL):{
362                 printf("set_lustre_upcall ");
363                 print_1_cfg(lcfg);
364                 break;
365         }
366         case(LCFG_PARAM):{
367                 printf("param ");
368                 print_1_cfg(lcfg);
369                 break;
370         }
371         case(LCFG_SPTLRPC_CONF):{
372                 printf("sptlrpc_conf ");
373                 print_1_cfg(lcfg);
374                 break;
375         }
376         case(LCFG_MARKER):{
377                 struct cfg_marker *marker = lustre_cfg_buf(lcfg, 1);
378                 char createtime[26], canceltime[26] = "";
379                 time_t time_tmp;
380
381                 if (marker->cm_flags & CM_SKIP) {
382                         if (marker->cm_flags & CM_START) {
383                                 printf("SKIP START ");
384                                 (*skip)++;
385                         } else {
386                                 printf(     "END   ");
387                                 *skip = 0;
388                         }
389                 }
390
391                 if (marker->cm_flags & CM_EXCLUDE) {
392                         if (marker->cm_flags & CM_START)
393                                 printf("EXCLUDE START ");
394                         else
395                                 printf("EXCLUDE END   ");
396                 }
397
398                 /* Handle overflow of 32-bit time_t gracefully.
399                  * The copy to time_tmp is needed in any case to
400                  * keep the pointer happy, even on 64-bit systems. */
401                 time_tmp = marker->cm_createtime;
402                 if (time_tmp == marker->cm_createtime) {
403                         ctime_r(&time_tmp, createtime);
404                         createtime[strlen(createtime) - 1] = 0;
405                 } else {
406                         strcpy(createtime, "in the distant future");
407                 }
408
409                 if (marker->cm_canceltime) {
410                         /* Like cm_createtime, we try to handle overflow of
411                          * 32-bit time_t gracefully. The copy to time_tmp
412                          * is also needed on 64-bit systems to keep the
413                          * pointer happy, see bug 16771 */
414                         time_tmp = marker->cm_canceltime;
415                         if (time_tmp == marker->cm_canceltime) {
416                                 ctime_r(&time_tmp, canceltime);
417                                 canceltime[strlen(canceltime) - 1] = 0;
418                         } else {
419                                 strcpy(canceltime, "in the distant future");
420                         }
421                 }
422
423                 printf("marker %3d (flags=%#04x, v%d.%d.%d.%d) %-15s '%s' %s-%s",
424                        marker->cm_step, marker->cm_flags,
425                        OBD_OCD_VERSION_MAJOR(marker->cm_vers),
426                        OBD_OCD_VERSION_MINOR(marker->cm_vers),
427                        OBD_OCD_VERSION_PATCH(marker->cm_vers),
428                        OBD_OCD_VERSION_FIX(marker->cm_vers),
429                        marker->cm_tgtname, marker->cm_comment,
430                        createtime, canceltime);
431                 break;
432         }
433         case(LCFG_POOL_NEW):{
434                 printf("pool new ");
435                 print_1_cfg(lcfg);
436                 break;
437         }
438         case(LCFG_POOL_ADD):{
439                 printf("pool add ");
440                 print_1_cfg(lcfg);
441                 break;
442         }
443         case(LCFG_POOL_REM):{
444                 printf("pool remove ");
445                 print_1_cfg(lcfg);
446                 break;
447         }
448         case(LCFG_POOL_DEL):{
449                 printf("pool destroy ");
450                 print_1_cfg(lcfg);
451                 break;
452         }
453         default:
454                 printf("unsupported cmd_code = %x\n",cmd);
455         }
456         printf("\n");
457         return;
458 }
459
460 void print_records(struct llog_rec_hdr **recs, int rec_number)
461 {
462         __u32 lopt;
463         int i, skip = 0;
464
465         for(i = 0; i < rec_number; i++) {
466                 printf("#%.2d (%.3d)", le32_to_cpu(recs[i]->lrh_index),
467                        le32_to_cpu(recs[i]->lrh_len));
468
469                 lopt = le32_to_cpu(recs[i]->lrh_type);
470
471                 if (recs[i]->lrh_padding == CANCELLED)
472                         printf("NOT SET ");
473
474                 if (lopt == OBD_CFG_REC) {
475                         struct lustre_cfg *lcfg;
476                         lcfg = (struct lustre_cfg *)((char*)(recs[i]) +
477                                                      sizeof(struct llog_rec_hdr));
478                         print_lustre_cfg(lcfg, &skip);
479                 } else if (lopt == LLOG_PAD_MAGIC) {
480                         printf("padding\n");
481                 } else
482                         printf("unknown type %x\n", lopt);
483         }
484 }