/* * write_chunks: write the chunk_buf on the device. The number of write * operations are based on the parameters write_end, offset, and chunksize. * * Returns 0 on success, or -ve error number on failure. */ int write_chunks(int fd, unsigned long long offset,unsigned long long write_end, char *chunk_buf, size_t chunksize, const time_t time_st, const ino_t inode_st, const char *file) { unsigned long long stride, count = 0; stride = full ? chunksize : (ONE_GB - chunksize); for (offset = offset & ~(chunksize - 1); offset < write_end; offset += stride) { int ret; if (lseek64(fd, offset, SEEK_SET) == -1) { fprintf(stderr, "\n%s: lseek64(%s+%llu) failed: %s\n", progname, file, offset, strerror(errno)); return -errno; } if (offset + chunksize > write_end) chunksize = write_end - offset; if (!full && offset > chunksize) { fill_chunk(chunk_buf, chunksize, offset, time_st, inode_st); ret = write_retry(fd, chunk_buf, chunksize, offset, file); if (ret < 0) return ret; offset += chunksize; count += chunksize; if (offset + chunksize > write_end) chunksize = write_end - offset; } fill_chunk(chunk_buf, chunksize, offset, time_st, inode_st); ret = write_retry(fd, chunk_buf, chunksize, offset, file); if (ret < 0) return ret; count += chunksize; if (verbose > 1) show_rate("write", offset, &count); } if (verbose > 1) { show_rate("write", offset, &count); printf("\nwrite complete\n"); } if (fsync(fd) == -1) { fprintf(stderr, "%s: fsync failed: %s\n", progname, strerror(errno)); return -errno; } return 0; }
static uint32_t flush_messages(bool now) { uint32_t flushed = 0; uint32_t len, pos = 0; uint8_t send_buf[32 * 1024]; struct msg_common *clr_msg; /* Not inited, can't flush */ if (fd < 0) return 0; if (!now && --flush_counter > 0) return 0; /* Make sure flush_counter cannot get to zero while calling flush_messages() */ flush_counter = 999999999; curr_flush_state = BUSY; clr_msg = (struct msg_common *) send_buf; clr_msg->magic = MSG_MAGIC_NUMBER; clr_msg->type = CLEAR; pos += sizeof(struct msg_common); len = sizeof(send_buf); flushed += flush_messages_in_store(get_alloc_msg_store(), send_buf, &len, &pos); flushed += flush_messages_in_store(get_files_msg_store(), send_buf, &len, &pos); if (pos > 0 && write_retry(fd, (uint8_t *) send_buf, pos) < 0) debug_exit("Could not send messages\n"); curr_flush_state = IDLE; flush_counter = max_flush_counter; return flushed; }
static __attribute__((constructor(101))) void ocheck_init() { struct proc_msg msg; const char *proc_name; const char *s; /* Do not re-initialize if already initialized and it's the same pid */ if (lib_inited && (pid == ourgetpid())) return; backtraces_set_max_backtraces(0); pid = ourgetpid(); if (pid < 0) debug_exit("Could not get pid\n"); if (!(proc_name = is_this_the_right_proc())) return; unlink("/tmp/ocheck.out"); debug("Initializing libocheck.so for %s.%u... ", proc_name, pid); initialize_sock(); parse_ignore_backtraces(); /* if max_flush_counter <= 0 then flush only on ocheck_fini() */ if ((s = getenv("FLUSH_COUNT")) && strlen(s)) max_flush_counter = atoi(s); flush_counter = max_flush_counter; debug(" Flush counter %u\n", flush_counter); ocheck_init_store(get_alloc_msg_store()); ocheck_init_store(get_files_msg_store()); /* We won't get here, since initialize_sock() calls exit(1) in case something does not init */ msg.magic = MSG_MAGIC_NUMBER; msg.type = PROC_NAME; snprintf(msg.name, sizeof(msg.name), "%s.%d", proc_name, pid); write_retry(fd, (uint8_t *)&msg, sizeof(msg)); debug("done\n"); lib_inited = true; backtraces_set_max_backtraces(BACK_FRAMES_COUNT); }
static uint32_t flush_messages_in_store(struct call_msg_store *store, uint8_t *send_buf, uint32_t *len, uint32_t *pos) { uint32_t i, flushed = 0; struct call_msg *messages = store->messages; for (i = 0; i < store->upper_index_limit && curr_flush_state == BUSY; i++) { if (messages[i].type == INVALID) continue; flushed++; memcpy(&send_buf[*pos], &messages[i], sizeof(messages[0])); *pos += sizeof(messages[0]); *len -= sizeof(messages[0]); if (*len >= sizeof(messages[0])) continue; if (write_retry(fd, (uint8_t *) send_buf, *pos) < 0) debug_exit("Could not send messages\n"); *pos = 0; *len = sizeof(send_buf); } return flushed; }