ltrack_stats.c
来自「lustre 1.6.5 source code」· C语言 代码 · 共 494 行 · 第 1/2 页
C
494 行
} } /* closing popen for llstat */ if (pclose(fp_popen) < 0) { fprintf(stderr, "Error: Couldn't pclos" " llstat popen call\n"); exit(1); } } /* child ends */ return pid_llstat_command;}pid_t fork_actual_command(int type, unsigned short id, char* stats_path, char* command){ pid_t pid; /* starting ltrack_stats functionality here */ if ((pid = fork()) < 0) fprintf(stderr, "Error: Fork error\n"); /* fork for executing command */ if (pid == 0) { switch(type) { case TRACK_BY_GID: if (setgid(id) < 0) { fprintf(stderr, "Error: failed to" " setgid\n"); exit(1); } pid = id; break; case TRACK_BY_PID: case TRACK_BY_PPID: pid = getpid(); break; /* 0 has to be written to vfs_track_pid to collect * statistics of all processes */ case TRACK_FOR_ALL: pid = 0; type = TRACK_BY_PID; break; } write_track_xid(type, pid, stats_path); execl("/bin/sh", "sh", "-c", command, (char *)0); exit(0); } /* child ends */ return(pid);}char* get_path_stats(int with_llstat, char* stats_path){ glob_t stats_glob_buffer; int choice; char error = 0; int i; /* No slots reserved in gl_pathv. Store the found path at 0 location */ stats_glob_buffer.gl_offs = 0; /* doing glob() for attaching llstat to monitor each vfs_ops_stat for * mulitiple lustre clients */ if (glob("/proc/fs/lustre/llite/*", GLOB_DOOFFS, NULL, &stats_glob_buffer) != 0) { fprintf(stderr,"Error: Couldn't find /proc entry for " "lustre\n"); exit(1); } /* If multiple client entries found in /proc/fs/lustre/llite user will * be prompted with choice of all */ if (stats_glob_buffer.gl_pathc > 1 && with_llstat) { check_llstat(); printf("Multiple lustre clients found, continuing... \n"); do { /* If flow is here again it means there was an error * and notifying that to user */ if (error) { system("clear"); fprintf(stderr, "Error: Please give correct " "choice.\n"); } /* Simple menu based interface to avoid possible * spelling mistakes */ printf("\t\tMenu.\n"); for (i = 0; i < stats_glob_buffer.gl_pathc; i++) printf("\t\t%d. %s\n", i+1, stats_glob_buffer.gl_pathv[i]); printf("\nEnter the lustre client number you want to " "use:"); scanf(" %d", &choice); error ++; } while (choice > stats_glob_buffer.gl_pathc || choice < 1); strcpy(stats_path, stats_glob_buffer.gl_pathv[choice - 1]); } else { /*if only one client then simply copying the path from glob */ strcpy(stats_path, stats_glob_buffer.gl_pathv[0]); } /* this frees dynamically allocated space by glob() for storing found * paths */ globfree(&stats_glob_buffer); return stats_path;}/* Writes the id (gid/ pid/ ppid) value in appropriate tracking proc entry file * and EXECs the command given */void fork_command(int type, unsigned short id, char* command, char* llstat_file){ pid_t pid_actual_command = 0; pid_t pid_llstat_command = 0; /* counters */ int with_llstat = 1; int status; char stats_path[1024]; char stats_path_temp[1024]; if (strlen(llstat_file) == 0) with_llstat = 0; get_path_stats(with_llstat, stats_path); strcpy(stats_path_temp, stats_path); /* llstat process attached to monitor given command */ if (with_llstat) pid_llstat_command = fork_llstat_command(llstat_file, stats_path_temp); /* forking a process which will exec command given */ pid_actual_command = fork_actual_command(type, id, stats_path, command); if (waitpid(pid_actual_command, NULL, 0) != pid_actual_command) fprintf(stderr, "Error: waitpid error\n"); if (with_llstat) { /* comment #25 of BUG 10968 */ sleep(2); /* sending kill to all llstat commands created for each * lustre-client respectively */ kill(pid_llstat_command, 9); waitpid(pid_llstat_command, &status, 0); /* if llstat child is killed by KILL only then print note for * plotting graph and if its exited normally with errornous * status then it means there were some error and llstat was * aborted*/ if (!WIFEXITED(status)) printf("\n\t[Note: Do \"$plot-llstat %s\" to plot a graph" " using GNU plot]\n", llstat_file); }}/* main */int main(int argc, char **argv){ char gid_string[5] = ""; gid_t gid; int c; char command[COMM_LEN] = ""; char llstat_file[100] = ""; /* Checking for root*/ if (getuid()) { fprintf(stderr, "Error: You need to be root\n"); exit(1); } opterr = 0; /* Parsing command line switches */ while ((c = getopt(argc, argv, "l:g:c:i:a:h")) != 1) switch (c) { case 'l': strcpy(llstat_file, optarg); if (strlen(llstat_file) > LEN_OUT) { fprintf(stderr, "length of outfile file" " is too long\n"); exit(1); } break; /* When any value is written to vfs_track_gid, then VFS * operation statistics are collected for all * processes of that group ID. * write_track_xid writes given <gid> in vfs_track_gid * here. */ case 'g': strcpy(gid_string, optarg); get_command_from_argv(optind, argc, argv, "", command); gid = atoi(gid_string); fork_command(TRACK_BY_GID, gid, command, llstat_file); return(0); /* When any value is written to vfs_track_ppid, then VFS * operation statistics are collected for all processes * whose parents' PID is same as track_ppid. *- write_track_xid writes pid to vfs_track_ppid here */ case 'c': get_command_from_argv(optind, argc, argv, optarg, command); fork_command(TRACK_BY_PPID, 0, command, llstat_file); return(0); /* When a non-zero value is written to vfs_track_pid, * then VFS operation statistics are collected for only * that PID.Write_track_xid writes pid to vfs_track_pid * here.Wei need to FORK a new process and EXEC it with * given <command>. */ case 'i': get_command_from_argv(optind, argc, argv, optarg, command); fork_command(TRACK_BY_PID, 0, command, llstat_file); return(0); /* When VFS operation statistics for all processes are * to be collected, "0" is written to vfs_track_pid. */ case 'a': get_command_from_argv(optind, argc, argv, optarg, command); fork_command(TRACK_FOR_ALL, 0, command, llstat_file); return(0); /* Help */ case 'h': print_usage(); return(0); default: print_usage(); return(1); } return(0);} /* main ends */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?