00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "includes.h"
00024
00025 #ifdef WITH_PROFILE
00026 #define IPC_PERMS ((S_IRUSR | S_IWUSR) | S_IRGRP | S_IROTH)
00027 #endif
00028
00029 #ifdef WITH_PROFILE
00030 static int shm_id;
00031 static BOOL read_only;
00032 #if defined(HAVE_CLOCK_GETTIME)
00033 clockid_t __profile_clock;
00034 BOOL have_profiling_clock = False;
00035 #endif
00036 #endif
00037
00038 struct profile_header *profile_h;
00039 struct profile_stats *profile_p;
00040
00041 BOOL do_profile_flag = False;
00042 BOOL do_profile_times = False;
00043
00044
00045
00046
00047 void set_profile_level(int level, struct process_id src)
00048 {
00049 #ifdef WITH_PROFILE
00050 switch (level) {
00051 case 0:
00052 do_profile_flag = False;
00053 do_profile_times = False;
00054 DEBUG(1,("INFO: Profiling turned OFF from pid %d\n",
00055 (int)procid_to_pid(&src)));
00056 break;
00057 case 1:
00058 do_profile_flag = True;
00059 do_profile_times = False;
00060 DEBUG(1,("INFO: Profiling counts turned ON from pid %d\n",
00061 (int)procid_to_pid(&src)));
00062 break;
00063 case 2:
00064
00065 #if defined(HAVE_CLOCK_GETTIME)
00066 if (!have_profiling_clock) {
00067 do_profile_flag = True;
00068 do_profile_times = False;
00069 DEBUG(1,("INFO: Profiling counts turned ON from "
00070 "pid %d\n", (int)procid_to_pid(&src)));
00071 DEBUGADD(1,("INFO: Profiling times disabled "
00072 "due to lack of a suitable clock\n"));
00073 break;
00074 }
00075 #endif
00076
00077 do_profile_flag = True;
00078 do_profile_times = True;
00079 DEBUG(1,("INFO: Full profiling turned ON from pid %d\n",
00080 (int)procid_to_pid(&src)));
00081 break;
00082 case 3:
00083 memset((char *)profile_p, 0, sizeof(*profile_p));
00084 DEBUG(1,("INFO: Profiling values cleared from pid %d\n",
00085 (int)procid_to_pid(&src)));
00086 break;
00087 }
00088 #else
00089 DEBUG(1,("INFO: Profiling support unavailable in this build.\n"));
00090 #endif
00091 }
00092
00093
00094
00095
00096 void profile_message(int msg_type, struct process_id src, void *buf, size_t len, void *private_data)
00097 {
00098 int level;
00099
00100 memcpy(&level, buf, sizeof(int));
00101 set_profile_level(level, src);
00102 }
00103
00104
00105
00106
00107 void reqprofile_message(int msg_type, struct process_id src,
00108 void *buf, size_t len, void *private_data)
00109 {
00110 int level;
00111
00112 #ifdef WITH_PROFILE
00113 level = 1 + (do_profile_flag?2:0) + (do_profile_times?4:0);
00114 #else
00115 level = 0;
00116 #endif
00117 DEBUG(1,("INFO: Received REQ_PROFILELEVEL message from PID %u\n",
00118 (unsigned int)procid_to_pid(&src)));
00119 message_send_pid(src, MSG_PROFILELEVEL, &level, sizeof(int), True);
00120 }
00121
00122
00123
00124
00125 #ifdef WITH_PROFILE
00126
00127 #ifdef HAVE_CLOCK_GETTIME
00128
00129
00130
00131
00132 static void init_clock_gettime(void)
00133 {
00134 struct timespec ts;
00135
00136 have_profiling_clock = False;
00137
00138 #ifdef HAVE_CLOCK_PROCESS_CPUTIME_ID
00139
00140
00141
00142
00143
00144
00145
00146 if (!this_is_smp()) {
00147 if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) == 0) {
00148 DEBUG(10, ("Using CLOCK_PROCESS_CPUTIME_ID "
00149 "for profile_clock\n"));
00150 __profile_clock = CLOCK_PROCESS_CPUTIME_ID;
00151 have_profiling_clock = True;
00152 }
00153 }
00154 #endif
00155
00156 #ifdef HAVE_CLOCK_MONOTONIC
00157 if (!have_profiling_clock &&
00158 clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
00159 DEBUG(10, ("Using CLOCK_MONOTONIC for profile_clock\n"));
00160 __profile_clock = CLOCK_MONOTONIC;
00161 have_profiling_clock = True;
00162 }
00163 #endif
00164
00165 #ifdef HAVE_CLOCK_REALTIME
00166
00167
00168
00169 if (!have_profiling_clock &&
00170 clock_gettime(CLOCK_REALTIME, &ts) == 0) {
00171 __profile_clock = CLOCK_REALTIME;
00172 have_profiling_clock = True;
00173
00174 SMB_WARN(__profile_clock != CLOCK_REALTIME,
00175 ("forced to use a slow profiling clock"));
00176 }
00177
00178 #endif
00179
00180 SMB_WARN(have_profiling_clock == True,
00181 ("could not find a working clock for profiling"));
00182 return;
00183 }
00184 #endif
00185
00186 BOOL profile_setup(BOOL rdonly)
00187 {
00188 struct shmid_ds shm_ds;
00189
00190 read_only = rdonly;
00191
00192 #ifdef HAVE_CLOCK_GETTIME
00193 init_clock_gettime();
00194 #endif
00195
00196 again:
00197
00198 shm_id = shmget(PROF_SHMEM_KEY, 0, 0);
00199
00200
00201
00202 if (shm_id == -1) {
00203 if (read_only) return False;
00204 shm_id = shmget(PROF_SHMEM_KEY, sizeof(*profile_h),
00205 IPC_CREAT | IPC_EXCL | IPC_PERMS);
00206 }
00207
00208 if (shm_id == -1) {
00209 DEBUG(0,("Can't create or use IPC area. Error was %s\n",
00210 strerror(errno)));
00211 return False;
00212 }
00213
00214
00215 profile_h = (struct profile_header *)shmat(shm_id, 0,
00216 read_only?SHM_RDONLY:0);
00217 if ((long)profile_p == -1) {
00218 DEBUG(0,("Can't attach to IPC area. Error was %s\n",
00219 strerror(errno)));
00220 return False;
00221 }
00222
00223
00224 if (shmctl(shm_id, IPC_STAT, &shm_ds) != 0) {
00225 DEBUG(0,("ERROR shmctl : can't IPC_STAT. Error was %s\n",
00226 strerror(errno)));
00227 return False;
00228 }
00229
00230 if (shm_ds.shm_perm.cuid != sec_initial_uid() ||
00231 shm_ds.shm_perm.cgid != sec_initial_gid()) {
00232 DEBUG(0,("ERROR: we did not create the shmem "
00233 "(owned by another user, uid %u, gid %u)\n",
00234 shm_ds.shm_perm.cuid,
00235 shm_ds.shm_perm.cgid));
00236 return False;
00237 }
00238
00239 if (shm_ds.shm_segsz != sizeof(*profile_h)) {
00240 DEBUG(0,("WARNING: profile size is %d (expected %lu). Deleting\n",
00241 (int)shm_ds.shm_segsz, sizeof(*profile_h)));
00242 if (shmctl(shm_id, IPC_RMID, &shm_ds) == 0) {
00243 goto again;
00244 } else {
00245 return False;
00246 }
00247 }
00248
00249 if (!read_only && (shm_ds.shm_nattch == 1)) {
00250 memset((char *)profile_h, 0, sizeof(*profile_h));
00251 profile_h->prof_shm_magic = PROF_SHM_MAGIC;
00252 profile_h->prof_shm_version = PROF_SHM_VERSION;
00253 DEBUG(3,("Initialised profile area\n"));
00254 }
00255
00256 profile_p = &profile_h->stats;
00257 message_register(MSG_PROFILE, profile_message, NULL);
00258 message_register(MSG_REQ_PROFILELEVEL, reqprofile_message, NULL);
00259 return True;
00260 }
00261
00262 const char * profile_value_name(enum profile_stats_values val)
00263 {
00264 static const char * valnames[PR_VALUE_MAX + 1] =
00265 {
00266 "smbd_idle",
00267 "syscall_opendir",
00268 "syscall_readdir",
00269 "syscall_seekdir",
00270 "syscall_telldir",
00271 "syscall_rewinddir",
00272 "syscall_mkdir",
00273 "syscall_rmdir",
00274 "syscall_closedir",
00275 "syscall_open",
00276 "syscall_close",
00277 "syscall_read",
00278 "syscall_pread",
00279 "syscall_write",
00280 "syscall_pwrite",
00281 "syscall_lseek",
00282 "syscall_sendfile",
00283 "syscall_rename",
00284 "syscall_fsync",
00285 "syscall_stat",
00286 "syscall_fstat",
00287 "syscall_lstat",
00288 "syscall_unlink",
00289 "syscall_chmod",
00290 "syscall_fchmod",
00291 "syscall_chown",
00292 "syscall_fchown",
00293 "syscall_chdir",
00294 "syscall_getwd",
00295 "syscall_ntimes",
00296 "syscall_ftruncate",
00297 "syscall_fcntl_lock",
00298 "syscall_kernel_flock",
00299 "syscall_linux_setlease",
00300 "syscall_fcntl_getlock",
00301 "syscall_readlink",
00302 "syscall_symlink",
00303 "syscall_link",
00304 "syscall_mknod",
00305 "syscall_realpath",
00306 "syscall_get_quota",
00307 "syscall_set_quota",
00308 "SMBmkdir",
00309 "SMBrmdir",
00310 "SMBopen",
00311 "SMBcreate",
00312 "SMBclose",
00313 "SMBflush",
00314 "SMBunlink",
00315 "SMBmv",
00316 "SMBgetatr",
00317 "SMBsetatr",
00318 "SMBread",
00319 "SMBwrite",
00320 "SMBlock",
00321 "SMBunlock",
00322 "SMBctemp",
00323 "SMBmknew",
00324 "SMBcheckpath",
00325 "SMBexit",
00326 "SMBlseek",
00327 "SMBlockread",
00328 "SMBwriteunlock",
00329 "SMBreadbraw",
00330 "SMBreadBmpx",
00331 "SMBreadBs",
00332 "SMBwritebraw",
00333 "SMBwriteBmpx",
00334 "SMBwriteBs",
00335 "SMBwritec",
00336 "SMBsetattrE",
00337 "SMBgetattrE",
00338 "SMBlockingX",
00339 "SMBtrans",
00340 "SMBtranss",
00341 "SMBioctl",
00342 "SMBioctls",
00343 "SMBcopy",
00344 "SMBmove",
00345 "SMBecho",
00346 "SMBwriteclose",
00347 "SMBopenX",
00348 "SMBreadX",
00349 "SMBwriteX",
00350 "SMBtrans2",
00351 "SMBtranss2",
00352 "SMBfindclose",
00353 "SMBfindnclose",
00354 "SMBtcon",
00355 "SMBtdis",
00356 "SMBnegprot",
00357 "SMBsesssetupX",
00358 "SMBulogoffX",
00359 "SMBtconX",
00360 "SMBdskattr",
00361 "SMBsearch",
00362 "SMBffirst",
00363 "SMBfunique",
00364 "SMBfclose",
00365 "SMBnttrans",
00366 "SMBnttranss",
00367 "SMBntcreateX",
00368 "SMBntcancel",
00369 "SMBntrename",
00370 "SMBsplopen",
00371 "SMBsplwr",
00372 "SMBsplclose",
00373 "SMBsplretq",
00374 "SMBsends",
00375 "SMBsendb",
00376 "SMBfwdname",
00377 "SMBcancelf",
00378 "SMBgetmac",
00379 "SMBsendstrt",
00380 "SMBsendend",
00381 "SMBsendtxt",
00382 "SMBinvalid",
00383 "pathworks_setdir",
00384 "Trans2_open",
00385 "Trans2_findfirst",
00386 "Trans2_findnext",
00387 "Trans2_qfsinfo",
00388 "Trans2_setfsinfo",
00389 "Trans2_qpathinfo",
00390 "Trans2_setpathinfo",
00391 "Trans2_qfileinfo",
00392 "Trans2_setfileinfo",
00393 "Trans2_fsctl",
00394 "Trans2_ioctl",
00395 "Trans2_findnotifyfirst",
00396 "Trans2_findnotifynext",
00397 "Trans2_mkdir",
00398 "Trans2_session_setup",
00399 "Trans2_get_dfs_referral",
00400 "Trans2_report_dfs_inconsistancy",
00401 "NT_transact_create",
00402 "NT_transact_ioctl",
00403 "NT_transact_set_security_desc",
00404 "NT_transact_notify_change",
00405 "NT_transact_rename",
00406 "NT_transact_query_security_desc",
00407 "NT_transact_get_user_quota",
00408 "NT_transact_set_user_quota",
00409 "get_nt_acl",
00410 "fget_nt_acl",
00411 "set_nt_acl",
00412 "fset_nt_acl",
00413 "chmod_acl",
00414 "fchmod_acl",
00415 "name_release",
00416 "name_refresh",
00417 "name_registration",
00418 "node_status",
00419 "name_query",
00420 "host_announce",
00421 "workgroup_announce",
00422 "local_master_announce",
00423 "master_browser_announce",
00424 "lm_host_announce",
00425 "get_backup_list",
00426 "reset_browser",
00427 "announce_request",
00428 "lm_announce_request",
00429 "domain_logon",
00430 "sync_browse_lists",
00431 "run_elections",
00432 "election",
00433 ""
00434 };
00435
00436 SMB_ASSERT(val >= 0);
00437 SMB_ASSERT(val < PR_VALUE_MAX);
00438 return valnames[val];
00439 }
00440
00441 #endif