2 Unix SMB/CIFS implementation.
3 store smbd profiling information in shared memory
4 Copyright (C) Andrew Tridgell 1999
5 Copyright (C) James Peach 2006
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "system/shmem.h"
24 #include "system/filesys.h"
26 #include "smbprofile.h"
28 #define PROF_SHMEM_KEY ((key_t)0x07021999)
29 #define PROF_SHM_MAGIC 0x6349985
30 #define PROF_SHM_VERSION 15
32 #define IPC_PERMS ((S_IRUSR | S_IWUSR) | S_IRGRP | S_IROTH)
35 static bool read_only
;
37 struct profile_header
{
40 struct profile_stats stats
;
43 static struct profile_header
*profile_h
;
44 struct profile_stats
*profile_p
;
46 bool do_profile_flag
= False
;
47 bool do_profile_times
= False
;
49 /****************************************************************************
50 Set a profiling level.
51 ****************************************************************************/
52 void set_profile_level(int level
, struct server_id src
)
55 case 0: /* turn off profiling */
56 do_profile_flag
= False
;
57 do_profile_times
= False
;
58 DEBUG(1,("INFO: Profiling turned OFF from pid %d\n",
59 (int)procid_to_pid(&src
)));
61 case 1: /* turn on counter profiling only */
62 do_profile_flag
= True
;
63 do_profile_times
= False
;
64 DEBUG(1,("INFO: Profiling counts turned ON from pid %d\n",
65 (int)procid_to_pid(&src
)));
67 case 2: /* turn on complete profiling */
68 do_profile_flag
= True
;
69 do_profile_times
= True
;
70 DEBUG(1,("INFO: Full profiling turned ON from pid %d\n",
71 (int)procid_to_pid(&src
)));
73 case 3: /* reset profile values */
74 memset((char *)profile_p
, 0, sizeof(*profile_p
));
75 DEBUG(1,("INFO: Profiling values cleared from pid %d\n",
76 (int)procid_to_pid(&src
)));
81 /****************************************************************************
82 receive a set profile level message
83 ****************************************************************************/
84 static void profile_message(struct messaging_context
*msg_ctx
,
92 if (data
->length
!= sizeof(level
)) {
93 DEBUG(0, ("got invalid profile message\n"));
97 memcpy(&level
, data
->data
, sizeof(level
));
98 set_profile_level(level
, src
);
101 /****************************************************************************
102 receive a request profile level message
103 ****************************************************************************/
104 static void reqprofile_message(struct messaging_context
*msg_ctx
,
107 struct server_id src
,
112 level
= 1 + (do_profile_flag
?2:0) + (do_profile_times
?4:0);
114 DEBUG(1,("INFO: Received REQ_PROFILELEVEL message from PID %u\n",
115 (unsigned int)procid_to_pid(&src
)));
116 messaging_send_buf(msg_ctx
, src
, MSG_PROFILELEVEL
,
117 (uint8
*)&level
, sizeof(level
));
120 /*******************************************************************
121 open the profiling shared memory area
122 ******************************************************************/
123 bool profile_setup(struct messaging_context
*msg_ctx
, bool rdonly
)
125 struct shmid_ds shm_ds
;
130 /* try to use an existing key */
131 shm_id
= shmget(PROF_SHMEM_KEY
, 0, 0);
133 /* if that failed then create one. There is a race condition here
134 if we are running from inetd. Bad luck. */
136 if (read_only
) return False
;
137 shm_id
= shmget(PROF_SHMEM_KEY
, sizeof(*profile_h
),
138 IPC_CREAT
| IPC_EXCL
| IPC_PERMS
);
142 DEBUG(0,("Can't create or use IPC area. Error was %s\n",
147 profile_h
= (struct profile_header
*)shmat(shm_id
, 0,
148 read_only
?SHM_RDONLY
:0);
149 if ((long)profile_h
== -1) {
150 DEBUG(0,("Can't attach to IPC area. Error was %s\n",
155 /* find out who created this memory area */
156 if (shmctl(shm_id
, IPC_STAT
, &shm_ds
) != 0) {
157 DEBUG(0,("ERROR shmctl : can't IPC_STAT. Error was %s\n",
162 if (shm_ds
.shm_perm
.cuid
!= sec_initial_uid() ||
163 shm_ds
.shm_perm
.cgid
!= sec_initial_gid()) {
164 DEBUG(0,("ERROR: we did not create the shmem "
165 "(owned by another user, uid %u, gid %u)\n",
166 shm_ds
.shm_perm
.cuid
,
167 shm_ds
.shm_perm
.cgid
));
171 if (shm_ds
.shm_segsz
!= sizeof(*profile_h
)) {
172 DEBUG(0,("WARNING: profile size is %d (expected %d). Deleting\n",
173 (int)shm_ds
.shm_segsz
, (int)sizeof(*profile_h
)));
174 if (shmctl(shm_id
, IPC_RMID
, &shm_ds
) == 0) {
181 if (!read_only
&& (shm_ds
.shm_nattch
== 1)) {
182 memset((char *)profile_h
, 0, sizeof(*profile_h
));
183 profile_h
->prof_shm_magic
= PROF_SHM_MAGIC
;
184 profile_h
->prof_shm_version
= PROF_SHM_VERSION
;
185 DEBUG(3,("Initialised profile area\n"));
188 profile_p
= &profile_h
->stats
;
189 if (msg_ctx
!= NULL
) {
190 messaging_register(msg_ctx
, NULL
, MSG_PROFILE
,
192 messaging_register(msg_ctx
, NULL
, MSG_REQ_PROFILELEVEL
,