Ticket #9150: 9150-v2.patch

File 9150-v2.patch, 8.2 KB (added by danielk, 10 years ago)

Synced to trunk

  • libs/libmythtv/ThreadedFileWriter.cpp

     
    1717#include "ThreadedFileWriter.h"
    1818#include "compat.h"
    1919#include "mythverbose.h"
    20 #include "mythconfig.h"
     20#include "mythconfig.h" // gives us HAVE_POSIX_FADVISE
    2121
    22 #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
    23 #define HAVE_FDATASYNC 1
    24 #else
    25 #define HAVE_FDATASYNC 0
     22#if HAVE_POSIX_FADVISE < 1
     23static int posix_fadvise(int, off_t, off_t, int) { return 0; }
     24#  if defined(__linux__)
     25#    warning "Not using fadvise on platform that supports it."
     26#  endif
    2627#endif
    2728
    2829#define LOC QString("TFW: ")
     
    358359    flush = false;
    359360}
    360361
    361 /** \fn ThreadedFileWriter::Sync(void)
    362  *  \brief flush data written to the file descriptor to disk.
     362/** \brief Flush data written to the file descriptor to disk.
    363363 *
    364  *   NOTE: This doesn't even try flush our queue of data.
    365  *   This only ensures that data which has already been sent
    366  *   to the kernel for this file is written to disk. This
    367  *   means that if this backend is writing the data over a
    368  *   network filesystem like NFS, then the data will be visible
    369  *   to the NFS server after this is called. It is also useful
    370  *   in preventing the kernel from buffering up so many writes
    371  *   that they steal the CPU for a long time when the write
    372  *   to disk actually occurs.
     364 *  This prevents freezing up Linux disk access on a running
     365 *  CFQ, AS, or Deadline as the disk write schedulers. It does
     366 *  this via two mechanism. One is a data sync using the best
     367 *  mechanism available (fdatasync then fsync). The second is
     368 *  by telling the kernel we do not intend to use the data just
     369 *  written anytime soon so other processes time-slices will
     370 *  not be used to deal with our excess dirty pages.
     371 *
     372 *  \note We used to also use sync_file_range on Linux, however
     373 *  this is incompatible with newer filesystems such as BRTFS and
     374 *  does not actually sync any blocks that have not been allocated
     375 *  yet so it was never really appropriate for ThreadedFileWriter.
     376 *
     377 *  \note We use standard posix calls for this, so any operating
     378 *  system supporting the calls will benefit, but this has been
     379 *  designed with Linux in mind. Other OS's may benefit from
     380 *  revisiting this function.
    373381 */
    374382void ThreadedFileWriter::Sync(void)
    375383{
    376384    if (fd >= 0)
    377385    {
    378 #if HAVE_SYNC_FILE_RANGE
    379             uint64_t write_position;
     386        /// Toss any data the kernel wrote to disk on it's own from
     387        /// the cache, so we don't get penalized for preserving it
     388        /// during the sync.
     389        int ret = posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
     390        if (ret)
     391            VERBOSE(VB_IMPORTANT, LOC + "fadvise error" + ENO);
    380392
    381             buflock.lock();
    382             write_position = m_file_wpos;
    383             buflock.unlock();
    384 
    385             if ((write_position - m_file_sync) > TFW_MAX_WRITE_SIZE ||
    386                 (write_position && m_file_sync < (uint64_t)tfw_min_write_size))
    387             {
    388                 sync_file_range(fd, m_file_sync, write_position - m_file_sync,
    389                                 SYNC_FILE_RANGE_WRITE);
    390                 m_file_sync = write_position;
    391             }
    392 #elif HAVE_FDATASYNC
    393             fdatasync(fd);
     393#if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
     394        // fdatasync tries to avoid updating metadata, but will in
     395        // practice always update metadata if any data is written
     396        // as the file will usually have grown.
     397        fdatasync(fd);
    394398#else
    395             fsync(fd);
     399        fsync(fd);
    396400#endif
     401
     402        // Toss any data we just synced from cache, so we don't
     403        // get penalized for it between now and the next sync.
     404        ret = posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
     405        if (ret)
     406            VERBOSE(VB_IMPORTANT, LOC + "fadvise error" + ENO);
    397407    }
    398408}
    399409
  • libs/libmythtv/RingBuffer.cpp

     
    4343#define O_BINARY 0
    4444#endif
    4545
     46#if HAVE_POSIX_FADVISE < 1
     47static int posix_fadvise(int, off_t, off_t, int) { return 0; }
     48#endif
     49
    4650// about one second at 35mbit
    4751const uint RingBuffer::kBufferSize = 4 * 1024 * 1024;
    4852const int  RingBuffer::kDefaultOpenTimeout = 2000; // ms
     
    423427                {
    424428                    if (0 == lseek(fd2, 0, SEEK_SET))
    425429                    {
    426 #if HAVE_POSIX_FADVISE
    427430                        posix_fadvise(fd2, 0, 0, POSIX_FADV_SEQUENTIAL);
    428 #endif
     431                        posix_fadvise(fd2, 0, 1*1024*1024, POSIX_FADV_WILLNEED);
    429432                        lasterror = 0;
    430433                        break;
    431434                    }
     
    12591262            poslock.lockForWrite();
    12601263            rbwlock.lockForWrite();
    12611264            internalreadpos += read_return;
     1265            off_t donotneed = internalreadpos;
    12621266            rbwpos = (rbwpos + read_return) % kBufferSize;
    12631267            VERBOSE(VB_FILE|VB_EXTRA,
    12641268                    LOC + QString("rbwpos += %1K requested %2K in read")
    12651269                    .arg(read_return/1024,3).arg(totfree/1024,3));
    12661270            rbwlock.unlock();
    12671271            poslock.unlock();
     1272
     1273            if (fd2 >=0 && donotneed > 0)
     1274                posix_fadvise(fd2, 0, donotneed, POSIX_FADV_DONTNEED);
    12681275        }
    12691276
    12701277        int used = kBufferSize - ReadBufFree();
     
    13441351    reallyrunning = false;
    13451352    readsallowed = false;
    13461353    delete [] readAheadBuffer;
     1354    readAheadBuffer = NULL;
    13471355
    1348     readAheadBuffer = NULL;
    13491356    rbwlock.unlock();
    13501357    rbrlock.unlock();
    13511358    rwlock.unlock();
     
    15011508            if (remotefile)
    15021509                remotefile->Seek(old_pos, SEEK_SET);
    15031510            else
     1511            {
    15041512                lseek64(fd2, old_pos, SEEK_SET);
     1513                posix_fadvise(fd2, old_pos, 1*1024*1024, POSIX_FADV_WILLNEED);
     1514            }
    15051515        }
    15061516        else
    15071517        {
     
    18691879                if (remotefile)
    18701880                    ret = remotefile->Seek(internalreadpos, SEEK_SET);
    18711881                else
     1882                {
    18721883                    ret = lseek64(fd2, internalreadpos, SEEK_SET);
     1884                    posix_fadvise(fd2, 0,
     1885                                  internalreadpos, POSIX_FADV_DONTNEED);
     1886                    posix_fadvise(fd2, internalreadpos,
     1887                                  1*1024*1024, POSIX_FADV_WILLNEED);
     1888                }
    18731889                VERBOSE(VB_FILE, LOC +
    18741890                        QString("Seek to %1 from ignore pos %2 returned %3")
    18751891                        .arg(internalreadpos).arg(ignorereadpos).arg(ret));
     
    19181934                new_pos = fi.size() - off_end;
    19191935            }
    19201936        }
     1937/*
    19211938#ifdef __FreeBSD__
    19221939        else if (llabs(new_pos-readpos) > 100000000LL)
    19231940#else
    19241941        else if (abs(new_pos-readpos) > 100000000LL)
    19251942#endif
     1943*/
     1944        else
    19261945        {
    19271946            if (remotefile)
    19281947            {
     
    19341953                off_end = fi.size() - new_pos;
    19351954            }
    19361955        }
    1937         if (off_end == 250000)
     1956
     1957        if (off_end != 0xDEADBEEF)
    19381958        {
    19391959            VERBOSE(VB_FILE, LOC +
     1960                    QString("Seek(): Offset from end: %1").arg(off_end));
     1961        }
     1962
     1963        if (off_end <= 250000)
     1964        {
     1965            VERBOSE(VB_FILE, LOC +
    19401966                    QString("Seek(): offset from end: %1").arg(off_end) +
    19411967                    "\n\t\t\t -- ignoring read ahead thread until next seek.");
    19421968
     
    19461972            if (remotefile)
    19471973                ret = remotefile->Seek(ignorereadpos, SEEK_SET);
    19481974            else
     1975            {
    19491976                ret = lseek64(fd2, ignorereadpos, SEEK_SET);
     1977                posix_fadvise(fd2, ignorereadpos, 250000, POSIX_FADV_WILLNEED);
     1978            }
    19501979
    19511980            if (ret < 0)
    19521981            {
     
    20292058    else
    20302059    {
    20312060        ret = lseek64(fd2, pos, whence);
     2061        if (ret >= 0)
     2062        {
     2063            posix_fadvise(fd2, 0,   ret,         POSIX_FADV_DONTNEED);
     2064            posix_fadvise(fd2, ret, 1*1024*1024, POSIX_FADV_WILLNEED);
     2065        }
    20322066    }
    20332067
    20342068    if (ret >= 0)