/* * pinger -- * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet * will be added on by the kernel. The ID field is our UNIX process ID, * and the sequence number is an ascending integer. The first 8 bytes * of the data portion are used to hold a UNIX "timeval" struct in VAX * byte-order, to compute the round-trip time. */ int pinger(void) { static int oom_count; static int tokens; int i; /* Have we already sent enough? If we have, return an arbitrary positive value. */ if (exiting || (npackets && ntransmitted >= npackets && !deadline)) return 1000; /* Check that packets < rate*time + preload */ if (cur_time.tv_sec == 0) { gettimeofday(&cur_time, NULL); tokens = interval*(preload-1); } else { long ntokens; struct timeval tv; gettimeofday(&tv, NULL); ntokens = (tv.tv_sec - cur_time.tv_sec)*1000 + (tv.tv_usec-cur_time.tv_usec)/1000; if (!interval) { /* Case of unlimited flood is special; * if we see no reply, they are limited to 100pps */ if (ntokens < MININTERVAL && in_flight() >= preload) return MININTERVAL-ntokens; } ntokens += tokens; if (ntokens > interval*preload) ntokens = interval*preload; if (ntokens < interval) return interval - ntokens; cur_time = tv; tokens = ntokens - interval; } if (options & F_OUTSTANDING) { if (ntransmitted > 0 && !rcvd_test(ntransmitted)) { print_timestamp(); printf("no answer yet for icmp_seq=%lu\n", (ntransmitted % MAX_DUP_CHK)); fflush(stdout); } } resend: i = send_probe(); if (i == 0) { oom_count = 0; advance_ntransmitted(); if (!(options & F_QUIET) && (options & F_FLOOD)) { /* Very silly, but without this output with * high preload or pipe size is very confusing. */ if ((preload < screen_width && pipesize < screen_width) || in_flight() < screen_width) write_stdout(".", 1); } return interval - tokens; } /* And handle various errors... */ if (i > 0) { /* Apparently, it is some fatal bug. */ abort(); } else if (errno == ENOBUFS || errno == ENOMEM) { int nores_interval; /* Device queue overflow or OOM. Packet is not sent. */ tokens = 0; /* Slowdown. This works only in adaptive mode (option -A) */ rtt_addend += (rtt < 8*50000 ? rtt/8 : 50000); if (options&F_ADAPTIVE) update_interval(); nores_interval = SCHINT(interval/2); if (nores_interval > 500) nores_interval = 500; oom_count++; if (oom_count*nores_interval < lingertime) return nores_interval; i = 0; /* Fall to hard error. It is to avoid complete deadlock * on stuck output device even when dealine was not requested. * Expected timings are screwed up in any case, but we will * exit some day. :-) */ } else if (errno == EAGAIN) { /* Socket buffer is full. */ tokens += interval; return MININTERVAL; } else { if ((i=receive_error_msg()) > 0) { /* An ICMP error arrived. */ tokens += interval; return MININTERVAL; } /* Compatibility with old linuces. */ if (i == 0 && confirm_flag && errno == EINVAL) { confirm_flag = 0; errno = 0; } if (!errno) goto resend; } /* Hard local error. Pretend we sent packet. */ advance_ntransmitted(); if (i == 0 && !(options & F_QUIET)) { if (options & F_FLOOD) write_stdout("E", 1); else perror("ping: sendmsg"); } tokens = 0; return SCHINT(interval); }
void main_loop(int icmp_sock, __u8 *packet, int packlen) { char addrbuf[128]; char ans_data[4096]; struct iovec iov; struct msghdr msg; struct cmsghdr *c; int cc; int next; int polling; iov.iov_base = (char *)packet; for (;;) { /* Check exit conditions. */ if (exiting) break; if (npackets && nreceived + nerrors >= npackets) break; if (deadline && nerrors) break; /* Check for and do special actions. */ if (status_snapshot) status(); /* Send probes scheduled to this time. */ do { next = pinger(); next = schedule_exit(next); } while (next <= 0); /* "next" is time to send next probe, if positive. * If next<=0 send now or as soon as possible. */ /* Technical part. Looks wicked. Could be dropped, * if everyone used the newest kernel. :-) * Its purpose is: * 1. Provide intervals less than resolution of scheduler. * Solution: spinning. * 2. Avoid use of poll(), when recvmsg() can provide * timed waiting (SO_RCVTIMEO). */ polling = 0; if ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || next<SCHINT(interval)) { int recv_expected = in_flight(); /* If we are here, recvmsg() is unable to wait for * required timeout. */ if (1000 % HZ == 0 ? next <= 1000 / HZ : (next < INT_MAX / HZ && next * HZ <= 1000)) { /* Very short timeout... So, if we wait for * something, we sleep for MININTERVAL. * Otherwise, spin! */ if (recv_expected) { next = MININTERVAL; } else { next = 0; /* When spinning, no reasons to poll. * Use nonblocking recvmsg() instead. */ polling = MSG_DONTWAIT; /* But yield yet. */ sched_yield(); } } if (!polling && ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || interval)) { struct pollfd pset; pset.fd = icmp_sock; pset.events = POLLIN|POLLERR; pset.revents = 0; if (poll(&pset, 1, next) < 1 || !(pset.revents&(POLLIN|POLLERR))) continue; polling = MSG_DONTWAIT; } } for (;;) { struct timeval *recv_timep = NULL; struct timeval recv_time; int not_ours = 0; /* Raw socket can receive messages * destined to other running pings. */ iov.iov_len = packlen; memset(&msg, 0, sizeof(msg)); msg.msg_name = addrbuf; msg.msg_namelen = sizeof(addrbuf); msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = ans_data; msg.msg_controllen = sizeof(ans_data); cc = recvmsg(icmp_sock, &msg, polling); polling = MSG_DONTWAIT; if (cc < 0) { if (errno == EAGAIN || errno == EINTR) break; if (!receive_error_msg()) { if (errno) { perror("ping: recvmsg"); break; } not_ours = 1; } } else { #ifdef SO_TIMESTAMP for (c = CMSG_FIRSTHDR(&msg); c; c = CMSG_NXTHDR(&msg, c)) { if (c->cmsg_level != SOL_SOCKET || c->cmsg_type != SO_TIMESTAMP) continue; if (c->cmsg_len < CMSG_LEN(sizeof(struct timeval))) continue; recv_timep = (struct timeval*)CMSG_DATA(c); } #endif if ((options&F_LATENCY) || recv_timep == NULL) { if ((options&F_LATENCY) || ioctl(icmp_sock, SIOCGSTAMP, &recv_time)) gettimeofday(&recv_time, NULL); recv_timep = &recv_time; } not_ours = parse_reply(&msg, cc, addrbuf, recv_timep); } /* See? ... someone runs another ping on this host. */ if (not_ours && !using_ping_socket) install_filter(); /* If nothing is in flight, "break" returns us to pinger. */ if (in_flight() == 0) break; /* Otherwise, try to recvmsg() again. recvmsg() * is nonblocking after the first iteration, so that * if nothing is queued, it will receive EAGAIN * and return to pinger. */ } } finish(); }
static int bc_ioacct_show(struct seq_file *f, void *v) { int i; unsigned long long read, write, cancel; unsigned long sync, sync_done; unsigned long fsync, fsync_done; unsigned long fdsync, fdsync_done; unsigned long frsync, frsync_done; unsigned long reads, writes; unsigned long long rchar, wchar; struct user_beancounter *ub; ub = seq_beancounter(f); read = write = cancel = 0; sync = sync_done = fsync = fsync_done = fdsync = fdsync_done = frsync = frsync_done = 0; reads = writes = 0; rchar = wchar = 0; for_each_online_cpu(i) { struct ub_percpu_struct *ub_percpu; ub_percpu = per_cpu_ptr(ub->ub_percpu, i); read += ub_percpu->bytes_read; write += ub_percpu->bytes_wrote; cancel += ub_percpu->bytes_cancelled; sync += ub_percpu->sync; fsync += ub_percpu->fsync; fdsync += ub_percpu->fdsync; frsync += ub_percpu->frsync; sync_done += ub_percpu->sync_done; fsync_done += ub_percpu->fsync_done; fdsync_done += ub_percpu->fdsync_done; frsync_done += ub_percpu->frsync_done; reads += ub_percpu->read; writes += ub_percpu->write; rchar += ub_percpu->rchar; wchar += ub_percpu->wchar; } seq_printf(f, bc_proc_llu_fmt, "read", read); seq_printf(f, bc_proc_llu_fmt, "write", ub->bytes_wrote + write); seq_printf(f, bc_proc_llu_fmt, "dirty", ub->bytes_dirtied); seq_printf(f, bc_proc_llu_fmt, "cancel", cancel); seq_printf(f, bc_proc_llu_fmt, "missed", ub->bytes_dirty_missed); seq_printf(f, bc_proc_lu_lfmt, "syncs_total", sync); seq_printf(f, bc_proc_lu_lfmt, "fsyncs_total", fsync); seq_printf(f, bc_proc_lu_lfmt, "fdatasyncs_total", fdsync); seq_printf(f, bc_proc_lu_lfmt, "range_syncs_total", frsync); seq_printf(f, bc_proc_lu_lfmt, "syncs_active", in_flight(sync)); seq_printf(f, bc_proc_lu_lfmt, "fsyncs_active", in_flight(fsync)); seq_printf(f, bc_proc_lu_lfmt, "fdatasyncs_active", in_flight(fsync)); seq_printf(f, bc_proc_lu_lfmt, "range_syncs_active", in_flight(frsync)); seq_printf(f, bc_proc_lu_lfmt, "vfs_reads", reads); seq_printf(f, bc_proc_llu_fmt, "vfs_read_chars", rchar); seq_printf(f, bc_proc_lu_lfmt, "vfs_writes", writes); seq_printf(f, bc_proc_llu_fmt, "vfs_write_chars", wchar); seq_printf(f, bc_proc_lu_lfmt, "io_pbs", ub->io_pb_held); return 0; }