/* Optionally flush file to disk and discard page cache */ void discard_file_cache(xc_interface *xch, int fd, int flush) { off_t cur = 0; int saved_errno = errno; if ( flush && (fsync(fd) < 0) ) { /*PERROR("Failed to flush file: %s", strerror(errno));*/ goto out; } /* * Calculate last page boundary of amount written so far * unless we are flushing in which case entire cache * is discarded. */ if ( !flush ) { if ( (cur = lseek(fd, 0, SEEK_CUR)) == (off_t)-1 ) cur = 0; cur &= ~(XC_PAGE_SIZE-1); } /* Discard from the buffer cache. */ if ( posix_fadvise64(fd, 0, cur, POSIX_FADV_DONTNEED) < 0 ) { /*PERROR("Failed to discard cache: %s", strerror(errno));*/ goto out; } out: errno = saved_errno; }
int DCOPY_open_input_fd(DCOPY_operation_t* op, \ off64_t offset, \ off64_t len) { int in_fd = open64(op->operand, O_RDONLY | O_NOATIME); if(in_fd < 0) { LOG(DCOPY_LOG_DBG, "Failed to open input file `%s'. %s", \ op->operand, strerror(errno)); /* Handle operation requeue in parent function. */ } posix_fadvise64(in_fd, offset, len, POSIX_FADV_SEQUENTIAL); return in_fd; }
int32_t SystemNative_PosixFAdvise(intptr_t fd, int64_t offset, int64_t length, int32_t advice) { #if HAVE_POSIX_ADVISE int32_t result; while (( result = #if HAVE_POSIX_FADVISE64 posix_fadvise64( #else posix_fadvise( #endif ToFileDescriptor(fd), (off_t)offset, (off_t)length, advice)) < 0 && errno == EINTR); return result; #else // Not supported on this platform. Caller can ignore this failure since it's just a hint. (void)fd, (void)offset, (void)length, (void)advice; return ENOTSUP; #endif }
CAMLprim value caml_extunix_fadvise64(value vfd, value voff, value vlen, value vadvise) { int errcode = 0; int fd = -1; off64_t off = 0; off64_t len = 0; int advise = 0; CAMLparam4(vfd, voff, vlen, vadvise); fd = Int_val(vfd); off = Int64_val(voff); len = Int64_val(vlen); advise = caml_advises[Int_val(vadvise)]; errcode = posix_fadvise64(fd, off, len, advise); if (errcode != 0) { unix_error(errcode, "fadvise64", Nothing); }; CAMLreturn(Val_unit); }
int posix_fadvise(int fd, off_t offset, off_t len, int advice) { return posix_fadvise64(fd, offset, len, advice); }
extern "C" Error SystemNative_Poll(PollEvent* pollEvents, uint32_t eventCount, int32_t milliseconds, uint32_t* triggered) { if (pollEvents == nullptr || triggered == nullptr) { return PAL_EFAULT; } if (milliseconds < -1) { return PAL_EINVAL; } size_t bufferSize; if (!multiply_s(sizeof(pollfd), static_cast<size_t>(eventCount), &bufferSize)) { return SystemNative_ConvertErrorPlatformToPal(EOVERFLOW); } bool useStackBuffer = bufferSize <= 2048; pollfd* pollfds = reinterpret_cast<pollfd*>(useStackBuffer ? alloca(bufferSize) : malloc(bufferSize)); if (pollfds == nullptr) { return PAL_ENOMEM; } for (uint32_t i = 0; i < eventCount; i++) { const PollEvent& event = pollEvents[i]; pollfds[i] = { .fd = event.FileDescriptor, .events = event.Events, .revents = 0 }; } int rv; while (CheckInterrupted(rv = poll(pollfds, static_cast<nfds_t>(eventCount), milliseconds))); if (rv < 0) { if (!useStackBuffer) { free(pollfds); } *triggered = 0; return SystemNative_ConvertErrorPlatformToPal(errno); } for (uint32_t i = 0; i < eventCount; i++) { const pollfd& pfd = pollfds[i]; assert(pfd.fd == pollEvents[i].FileDescriptor); assert(pfd.events == pollEvents[i].Events); pollEvents[i].TriggeredEvents = static_cast<PollEvents>(pfd.revents); } *triggered = static_cast<uint32_t>(rv); if (!useStackBuffer) { free(pollfds); } return PAL_SUCCESS; } extern "C" int32_t SystemNative_PosixFAdvise(intptr_t fd, int64_t offset, int64_t length, FileAdvice advice) { #if HAVE_POSIX_ADVISE int32_t result; while (CheckInterrupted( result = #if HAVE_POSIX_FADVISE64 posix_fadvise64( #else posix_fadvise( #endif ToFileDescriptor(fd), offset, length, advice))); return result; #else // Not supported on this platform. Caller can ignore this failure since it's just a hint. (void)fd, (void)offset, (void)length, (void)advice; return ENOTSUP; #endif }
bool BlockData::WriteFile(const boost::filesystem::path& block_file_path) { if (bytes_ == 0) { LOG4CPLUS_WARN(Loggers::Service(), "An attempt to write an empty block into file "<<block_file_path<<" is rejected."); return false; } bool direct_io_applicable = ((bytes_ % MemoryChunk::GetPageSize()) == 0); int open_flags = O_CREAT | O_WRONLY; if (direct_io_applicable) { open_flags |= (O_DIRECT | O_SYNC); } LOG4CPLUS_TRACE(Loggers::Service(), "DIRECT IO:"<<direct_io_applicable<<", bytes_:"<<bytes_<<", page_size:"<<MemoryChunk::GetPageSize()<<", bytes%pagesize="<<(bytes_%MemoryChunk::GetPageSize())); int file_descriptor = open(block_file_path.string().c_str(), open_flags, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); if (file_descriptor < 0) { LOG4CPLUS_ERROR(Loggers::Service(), "Failed to open file "<<block_file_path<<" to write."); return false; } size_t bytes_left = bytes_; size_t offset(0); int bytes_written(0); do { bytes_written = pwrite(file_descriptor, block_data_bytes_ + offset, bytes_left, offset); if (bytes_written > 0) { offset += bytes_written; bytes_left -= bytes_written; } } while(bytes_written > 0 && bytes_left > 0); if (bytes_written < 0) { LOG4CPLUS_ERROR(Loggers::Service(), "An error occurred while writing to file "<<block_file_path<<".(bytes_="<<bytes_<<", bytes_left="<<bytes_left<<")"); } if (!direct_io_applicable) { //data would have to be flushed out before it can be wiped from page cache if (fdatasync(file_descriptor) == 0) { //to advise system NOT to keep the data in page cache //note that option POSIX_FADV_NOREUSE is no-op on linux, and should not be used if (0 != posix_fadvise64(file_descriptor, 0, 0, POSIX_FADV_DONTNEED)) { LOG4CPLUS_WARN(Loggers::Service(), "Failed to advise system to free file data from page cache."); } } else { LOG4CPLUS_WARN(Loggers::Service(), "Failed to flush data into memory"); } } close(file_descriptor); return bytes_left == 0; }