Whamcloud - gitweb
This update includes Hex error ID's and checksum calculation for console error messages.
[fs/lustre-release.git] / lnet / klnds / ptllnd / ptllnd_ptltrace.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. All rights reserved.
5  *
6  *   This file is part of the Lustre file system, http://www.lustre.org
7  *   Lustre is a trademark of Cluster File Systems, Inc.
8  *
9  *   This file is confidential source code owned by Cluster File Systems.
10  *   No viewing, modification, compilation, redistribution, or any other
11  *   form of use is permitted except through a signed license agreement.
12  *
13  *   If you have not signed such an agreement, then you have no rights to
14  *   this file.  Please destroy it immediately and contact CFS.
15  *
16  */
17
18 #include "ptllnd.h"
19
20 #ifdef CRAY_XT3
21 static struct semaphore   ptltrace_mutex;
22 static struct semaphore   ptltrace_signal;
23
24 void
25 kptllnd_ptltrace_to_file(char *filename)
26 {
27         CFS_DECL_JOURNAL_DATA;
28         CFS_DECL_MMSPACE;
29
30         cfs_file_t *filp;
31         char       *start;
32         char       *tmpbuf;
33         int         len;
34         int         rc;
35         loff_t      offset = 0;
36         int         eof = 0;
37
38         CWARN("dumping ptltrace to %s\n", filename);
39
40         LIBCFS_ALLOC(tmpbuf, PAGE_SIZE);
41         if (tmpbuf == NULL) {
42                 CERROR("Can't allocate page buffer to dump %s\n", filename);
43                 return;
44         }
45         
46         CFS_PUSH_JOURNAL;
47
48         filp = cfs_filp_open(filename,
49                              O_CREAT|O_EXCL|O_WRONLY|O_LARGEFILE, 0600, &rc);
50         if (filp == NULL) {
51                 if (rc != -EEXIST)
52                         CERROR("Error %d creating %s\n", rc, filename);
53                 goto out;
54         }
55
56         CFS_MMSPACE_OPEN;
57
58         while (!eof) { 
59                 start = NULL; 
60                 len = ptl_proc_read(tmpbuf, &start, offset,
61                                     PAGE_SIZE, &eof, NULL);
62
63                 /* we don't allow ptl_proc_read to mimic case 0 or 1 behavior
64                  * for a proc_read method, only #2: from proc_file_read
65                  *
66                  * 2) Set *start = an address within the buffer.
67                  *    Put the data of the requested offset at *start.
68                  *    Return the number of bytes of data placed there.
69                  *    If this number is greater than zero and you
70                  *    didn't signal eof and the reader is prepared to
71                  *    take more data you will be called again with the
72                  *    requested offset advanced by the number of bytes
73                  *    absorbed.
74                  */
75
76                 if (len == 0)   /* end of file */
77                         break;
78
79                 if (len < 0) {
80                         CERROR("ptl_proc_read: error %d\n", len);
81                         break;
82                 }
83
84                 if (start < tmpbuf || start + len > tmpbuf + PAGE_SIZE) {
85                         CERROR("ptl_proc_read bug: %p for %d not in %p for %d\n",
86                                start, len, tmpbuf, PAGE_SIZE);
87                         break;
88                 }
89
90                 rc = cfs_filp_write(filp, start, len, cfs_filp_poff(filp));
91                 if (rc != len) {
92                         if (rc < 0)
93                                 CERROR("Error %d writing %s\n", rc, filename);
94                         else
95                                 CERROR("Partial write %d(%d) to %s\n",
96                                        rc, len, filename);
97                         break;
98                 }
99
100                 offset += len;
101         }
102
103         CFS_MMSPACE_CLOSE;
104
105         rc = cfs_filp_fsync(filp);
106         if (rc != 0)
107                 CERROR("Error %d syncing %s\n", rc, filename);
108
109         cfs_filp_close(filp);
110 out:
111         CFS_POP_JOURNAL;
112         LIBCFS_FREE(tmpbuf, PAGE_SIZE);
113 }
114
115 int
116 kptllnd_dump_ptltrace_thread(void *arg)
117 {
118         static char fname[1024];
119
120         libcfs_daemonize("ptltracedump");
121
122         /* serialise with other instances of me */
123         mutex_down(&ptltrace_mutex);
124
125         snprintf(fname, sizeof(fname), "%s.%ld.%ld",
126                  *kptllnd_tunables.kptl_ptltrace_basename,
127                  cfs_time_current_sec(), (long)arg);
128
129         kptllnd_ptltrace_to_file(fname);
130
131         mutex_up(&ptltrace_mutex);
132
133         /* unblock my creator */
134         mutex_up(&ptltrace_signal);
135         
136         return 0;
137 }
138
139 void
140 kptllnd_dump_ptltrace(void)
141 {
142         int            rc;     
143
144         if (!*kptllnd_tunables.kptl_ptltrace_on_timeout)
145                 return;
146
147         rc = cfs_kernel_thread(kptllnd_dump_ptltrace_thread,
148                                (void *)(long)cfs_curproc_pid(),
149                                CLONE_VM | CLONE_FS | CLONE_FILES);
150         if (rc < 0) {
151                 CERROR("Error %d starting ptltrace dump thread\n", rc);
152         } else {
153                 /* block until thread completes */
154                 mutex_down(&ptltrace_signal);
155         }
156 }
157
158 void
159 kptllnd_init_ptltrace(void)
160 {
161         init_mutex(&ptltrace_mutex);
162         init_mutex_locked(&ptltrace_signal);
163 }
164
165 #else
166
167 void
168 kptllnd_dump_ptltrace(void)
169 {
170 }
171
172 void
173 kptllnd_init_ptltrace(void)
174 {
175 }
176
177 #endif