Whamcloud - gitweb
Mass conversion of all copyright messages to Oracle.
[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  * 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 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  */
36
37 #include "ptllnd.h"
38
39 #ifdef CRAY_XT3
40 static cfs_semaphore_t    ptltrace_mutex;
41 static cfs_waitq_t        ptltrace_debug_ctlwq;
42
43 void
44 kptllnd_ptltrace_to_file(char *filename)
45 {
46         CFS_DECL_JOURNAL_DATA;
47         CFS_DECL_MMSPACE;
48
49         cfs_file_t *filp;
50         char       *start;
51         char       *tmpbuf;
52         int         len;
53         int         rc;
54         loff_t      offset = 0;
55         int         eof = 0;
56
57         CWARN("dumping ptltrace to %s\n", filename);
58
59         LIBCFS_ALLOC(tmpbuf, PAGE_SIZE);
60         if (tmpbuf == NULL) {
61                 CERROR("Can't allocate page buffer to dump %s\n", filename);
62                 return;
63         }
64         
65         CFS_PUSH_JOURNAL;
66
67         filp = cfs_filp_open(filename,
68                              O_CREAT|O_EXCL|O_WRONLY|O_LARGEFILE, 0600, &rc);
69         if (filp == NULL) {
70                 if (rc != -EEXIST)
71                         CERROR("Error %d creating %s\n", rc, filename);
72                 goto out;
73         }
74
75         CFS_MMSPACE_OPEN;
76
77         while (!eof) { 
78                 start = NULL; 
79                 len = ptl_proc_read(tmpbuf, &start, offset,
80                                     PAGE_SIZE, &eof, NULL);
81
82                 /* we don't allow ptl_proc_read to mimic case 0 or 1 behavior
83                  * for a proc_read method, only #2: from proc_file_read
84                  *
85                  * 2) Set *start = an address within the buffer.
86                  *    Put the data of the requested offset at *start.
87                  *    Return the number of bytes of data placed there.
88                  *    If this number is greater than zero and you
89                  *    didn't signal eof and the reader is prepared to
90                  *    take more data you will be called again with the
91                  *    requested offset advanced by the number of bytes
92                  *    absorbed.
93                  */
94
95                 if (len == 0)   /* end of file */
96                         break;
97
98                 if (len < 0) {
99                         CERROR("ptl_proc_read: error %d\n", len);
100                         break;
101                 }
102
103                 if (start < tmpbuf || start + len > tmpbuf + PAGE_SIZE) {
104                         CERROR("ptl_proc_read bug: %p for %d not in %p for %ld\n",
105                                start, len, tmpbuf, PAGE_SIZE);
106                         break;
107                 }
108
109                 rc = cfs_filp_write(filp, start, len, cfs_filp_poff(filp));
110                 if (rc != len) {
111                         if (rc < 0)
112                                 CERROR("Error %d writing %s\n", rc, filename);
113                         else
114                                 CERROR("Partial write %d(%d) to %s\n",
115                                        rc, len, filename);
116                         break;
117                 }
118
119                 offset += len;
120         }
121
122         CFS_MMSPACE_CLOSE;
123
124         rc = cfs_filp_fsync(filp);
125         if (rc != 0)
126                 CERROR("Error %d syncing %s\n", rc, filename);
127
128         cfs_filp_close(filp);
129 out:
130         CFS_POP_JOURNAL;
131         LIBCFS_FREE(tmpbuf, PAGE_SIZE);
132 }
133
134 int
135 kptllnd_dump_ptltrace_thread(void *arg)
136 {
137         static char fname[1024];
138
139         libcfs_daemonize("kpt_ptltrace_dump");
140
141         /* serialise with other instances of me */
142         cfs_mutex_down(&ptltrace_mutex);
143
144         snprintf(fname, sizeof(fname), "%s.%ld.%ld",
145                  *kptllnd_tunables.kptl_ptltrace_basename,
146                  cfs_time_current_sec(), (long)arg);
147
148         kptllnd_ptltrace_to_file(fname);
149
150         cfs_mutex_up(&ptltrace_mutex);
151
152         /* unblock my creator */
153         cfs_waitq_signal(&ptltrace_debug_ctlwq);
154         return 0;
155 }
156
157 void
158 kptllnd_dump_ptltrace(void)
159 {
160         int            rc;
161         cfs_waitlink_t wait;
162         ENTRY;
163
164         /* taken from libcfs_debug_dumplog */
165         cfs_waitlink_init(&wait);
166         cfs_set_current_state(CFS_TASK_INTERRUPTIBLE);
167         cfs_waitq_add(&ptltrace_debug_ctlwq, &wait);
168
169         rc = cfs_kernel_thread(kptllnd_dump_ptltrace_thread,
170                                (void *)(long)cfs_curproc_pid(),
171                                CLONE_VM | CLONE_FS | CLONE_FILES);
172         if (rc < 0) {
173                 CERROR("Error %d starting ptltrace dump thread\n", rc);
174         } else {
175                 cfs_waitq_wait(&wait, CFS_TASK_INTERRUPTIBLE);
176         }
177
178         /* teardown if cfs_kernel_thread() failed */
179         cfs_waitq_del(&ptltrace_debug_ctlwq, &wait);
180         cfs_set_current_state(CFS_TASK_RUNNING);
181         EXIT;
182 }
183
184 void
185 kptllnd_init_ptltrace(void)
186 {
187         cfs_waitq_init(&ptltrace_debug_ctlwq);
188         cfs_init_mutex(&ptltrace_mutex);
189 }
190 #endif