Whamcloud - gitweb
Landing b_hd_newconfig on HEAD
[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                 CERROR("Error %d creating %s\n", rc, filename);
52                 goto out;
53         }
54
55         CFS_MMSPACE_OPEN;
56
57         while (!eof) { 
58                 start = NULL; 
59                 len = ptl_proc_read(tmpbuf, &start, offset,
60                                     PAGE_SIZE, &eof, NULL);
61
62                 /* we don't allow ptl_proc_read to mimic case 0 or 1 behavior
63                  * for a proc_read method, only #2: from proc_file_read
64                  *
65                  * 2) Set *start = an address within the buffer.
66                  *    Put the data of the requested offset at *start.
67                  *    Return the number of bytes of data placed there.
68                  *    If this number is greater than zero and you
69                  *    didn't signal eof and the reader is prepared to
70                  *    take more data you will be called again with the
71                  *    requested offset advanced by the number of bytes
72                  *    absorbed.
73                  */
74
75                 if (len == 0)   /* end of file */
76                         break;
77
78                 if (len < 0) {
79                         CERROR("ptl_proc_read: error %d\n", len);
80                         break;
81                 }
82
83                 LASSERT (start >= tmpbuf && start + len <= tmpbuf + PAGE_SIZE);
84
85                 rc = cfs_filp_write(filp, start, len, cfs_filp_poff(filp));
86                 if (rc != len) {
87                         if (rc < 0)
88                                 CERROR("Error %d writing %s\n", rc, filename);
89                         else
90                                 CERROR("Partial write %d(%d) to %s\n",
91                                        rc, len, filename);
92                         break;
93                 }
94
95                 offset += len;
96         }
97
98         CFS_MMSPACE_CLOSE;
99
100         rc = cfs_filp_fsync(filp);
101         if (rc != 0)
102                 CERROR("Error %d syncing %s\n", rc, filename);
103
104         cfs_filp_close(filp);
105 out:
106         CFS_POP_JOURNAL;
107         LIBCFS_FREE(tmpbuf, PAGE_SIZE);
108 }
109
110 int
111 kptllnd_dump_ptltrace_thread(void *arg)
112 {
113         static char fname[1024];
114
115         libcfs_daemonize("ptltracedump");
116
117         /* serialise with other instances of me */
118         mutex_down(&ptltrace_mutex);
119
120         snprintf(fname, sizeof(fname), "%s.%ld.%ld",
121                  *kptllnd_tunables.kptl_ptltrace_basename,
122                  cfs_time_current_sec(), (long)arg);
123
124         kptllnd_ptltrace_to_file(fname);
125
126         mutex_up(&ptltrace_mutex);
127
128         /* unblock my creator */
129         mutex_up(&ptltrace_signal);
130         
131         return 0;
132 }
133
134 void
135 kptllnd_dump_ptltrace(void)
136 {
137         int            rc;     
138
139         if (!*kptllnd_tunables.kptl_ptltrace_on_timeout)
140                 return;
141
142         rc = cfs_kernel_thread(kptllnd_dump_ptltrace_thread,
143                                (void *)(long)cfs_curproc_pid(),
144                                CLONE_VM | CLONE_FS | CLONE_FILES);
145         if (rc < 0) {
146                 CERROR("Error %d starting ptltrace dump thread\n", rc);
147         } else {
148                 /* block until thread completes */
149                 mutex_down(&ptltrace_signal);
150         }
151 }
152
153 void
154 kptllnd_init_ptltrace(void)
155 {
156         init_mutex(&ptltrace_mutex);
157         init_mutex_locked(&ptltrace_signal);
158 }
159
160 #else
161
162 void
163 kptllnd_dump_ptltrace(void)
164 {
165 }
166
167 void
168 kptllnd_init_ptltrace(void)
169 {
170 }
171
172 #endif