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 + -
显示快捷键?