Skip to content

Commit

Permalink
Merge pull request xbmc#15686 from peak3d/nfs
Browse files Browse the repository at this point in the history
[NFS] Implement nfs timeout / advancedsettings
  • Loading branch information
peak3d authored and Maven85 committed Aug 6, 2020
1 parent a8d792b commit e6bbaf0
Show file tree
Hide file tree
Showing 10 changed files with 102 additions and 35 deletions.
38 changes: 38 additions & 0 deletions cmake/modules/FindNFS.cmake
Expand Up @@ -36,6 +36,44 @@ if(NFS_FOUND)
set(NFS_INCLUDE_DIRS ${NFS_INCLUDE_DIR})
set(NFS_DEFINITIONS -DHAS_FILESYSTEM_NFS=1)

set(CMAKE_REQUIRED_INCLUDES "${NFS_INCLUDE_DIR}")
set(CMAKE_REQUIRED_LIBRARIES ${NFS_LIBRARY})
if(CMAKE_SYSTEM_NAME MATCHES "Windows")
set(NFS_CXX_INCLUDE "#include <Winsock2.h>")
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} "ws2_32.lib")
endif()

# Check for nfs_set_timeout
check_cxx_source_compiles("
${NFS_CXX_INCLUDE}
#include <nfsc/libnfs.h>
int main()
{
nfs_set_timeout(NULL, 0);
}
" NFS_SET_TIMEOUT)

if(NFS_SET_TIMEOUT)
list(APPEND NFS_DEFINITIONS -DHAS_NFS_SET_TIMEOUT)
endif()

# Check for mount_getexports_timeout
check_cxx_source_compiles("
${NFS_CXX_INCLUDE}
#include <nfsc/libnfs.h>
int main()
{
mount_getexports_timeout(NULL, 0);
}
" NFS_MOUNT_GETEXPORTS_TIMEOUT)

if(NFS_MOUNT_GETEXPORTS_TIMEOUT)
list(APPEND NFS_DEFINITIONS -DHAS_NFS_MOUNT_GETEXPORTS_TIMEOUT)
endif()

unset(CMAKE_REQUIRED_INCLUDES)
unset(CMAKE_REQUIRED_LIBRARIES)

if(NOT TARGET NFS::NFS)
add_library(NFS::NFS UNKNOWN IMPORTED)
if(NFS_LIBRARY)
Expand Down
Expand Up @@ -22,7 +22,7 @@ libcdio-2.1.0-win10-arm-v141-20200112.7z
libfribidi-1.0.8-win10-arm-v141-20200105.7z
libiconv-1.16-win10-arm-v141-20200105.7z
libmicrohttpd-0.9.69-win10-arm-v141-20200105.7z
libnfs-4.0.0-win10-arm-v141-20200105.7z
libnfs-4.0.0-win10-arm-v142-20200605.7z
libudfread-1.0.0-win10-arm-v141-20200411.7z
libxml2-2.9.9-win10-arm-v141-20200105.7z
libxslt-1.1.34-win10-arm-v141-20200105.7z
Expand Down
Expand Up @@ -22,7 +22,7 @@ libcdio-2.1.0-win10-win32-v141-20200112.7z
libfribidi-1.0.8-win10-win32-v141-20200105.7z
libiconv-1.16-win10-win32-v141-20200105.7z
libmicrohttpd-0.9.69-win10-win32-v141-20200105.7z
libnfs-4.0.0-win10-win32-v141-20200105.7z
libnfs-4.0.0-win10-win32-v142-20200605.7z
libudfread-1.0.0-win10-win32-v141-20200411.7z
libxml2-2.9.9-win10-win32-v141-20200105.7z
libxslt-1.1.34-win10-win32-v141-20200105.7z
Expand Down
Expand Up @@ -22,7 +22,7 @@ libcdio-2.1.0-win10-x64-v141-20200112.7z
libfribidi-1.0.8-win10-x64-v141-20200105.7z
libiconv-1.16-win10-x64-v141-20200105.7z
libmicrohttpd-0.9.69-win10-x64-v141-20200105.7z
libnfs-4.0.0-win10-x64-v141-20200105.7z
libnfs-4.0.0-win10-x64-v142-20200605.7z
libudfread-1.0.0-win10-x64-v141-20200411.7z
libxml2-2.9.9-win10-x64-v141-20200105.7z
libxslt-1.1.34-win10-x64-v141-20200105.7z
Expand Down
Expand Up @@ -27,7 +27,7 @@ libfribidi-1.0.8-win32-v141-20200105.7z
libiconv-1.16-win10-win32-v141-20200105.7z
libjpeg-turbo-2.0.3-win32-v141-20200105.7z
libmicrohttpd-0.9.69-win32-v141-20200105.7z
libnfs-4.0.0-win32-v141-20200105.7z
libnfs-4.0.0-win32-v142-20200605.7z
libplist-2.1.0-win32-v141-20200105.7z
libpng-1.6.37-win32-v141-20200105.7z
libudfread-1.0.0-win32-v141-20200411.7z
Expand Down
Expand Up @@ -25,7 +25,7 @@ libcec-4.0.4-x64-v141-20200105.7z
libfribidi-1.0.8-x64-v141-20200105.7z
libiconv-1.16-x64-v141-20200105.7z
libmicrohttpd-0.9.69-x64-v141-20200105.7z
libnfs-4.0.0-x64-v141-20200105.7z
libnfs-4.0.0-x64-v142-20200605.7z
libplist-2.1.0-x64-v141-20200105.7z
libudfread-1.0.0-x64-v141-20200411.7z
libxml2-2.9.9-x64-v141-20200105.7z
Expand Down
77 changes: 47 additions & 30 deletions xbmc/filesystem/NFSFile.cpp
Expand Up @@ -12,7 +12,10 @@

#include "NFSFile.h"

#include "ServiceBroker.h"
#include "network/DNSNameCache.h"
#include "settings/AdvancedSettings.h"
#include "settings/SettingsComponent.h"
#include "threads/SingleLock.h"
#include "threads/SystemClock.h"
#include "utils/StringUtils.h"
Expand All @@ -29,19 +32,19 @@
#include <sys\stat.h>
#endif

//KEEP_ALIVE_TIMEOUT is decremented every half a second
//360 * 0.5s == 180s == 3mins
//so when no read was done for 3mins and files are open
//do the nfs keep alive for the open files
// KEEP_ALIVE_TIMEOUT is decremented every half a second
// 360 * 0.5s == 180s == 3mins
// so when no read was done for 3mins and files are open
// do the nfs keep alive for the open files
#define KEEP_ALIVE_TIMEOUT 360

//6 mins (360s) cached context timeout
// 6 mins (360s) cached context timeout
#define CONTEXT_TIMEOUT 360000

//return codes for getContextForExport
#define CONTEXT_INVALID 0 //getcontext failed
#define CONTEXT_NEW 1 //new context created
#define CONTEXT_CACHED 2 //context cached and therefore already mounted (no new mount needed)
// return codes for getContextForExport
#define CONTEXT_INVALID 0 // getcontext failed
#define CONTEXT_NEW 1 // new context created
#define CONTEXT_CACHED 2 // context cached and therefore already mounted (no new mount needed)

#if defined(TARGET_WINDOWS)
#define S_IRGRP 0
Expand All @@ -53,10 +56,7 @@
using namespace XFILE;

CNfsConnection::CNfsConnection()
: m_pNfsContext(NULL)
, m_exportPath("")
, m_hostName("")
, m_resolvedHostName("")
: m_pNfsContext(NULL), m_exportPath(""), m_hostName(""), m_resolvedHostName("")
{
}

Expand All @@ -65,32 +65,38 @@ CNfsConnection::~CNfsConnection()
Deinit();
}

void CNfsConnection::resolveHost(const CURL &url)
void CNfsConnection::resolveHost(const CURL& url)
{
//resolve if hostname has changed
// resolve if hostname has changed
CDNSNameCache::Lookup(url.GetHostName(), m_resolvedHostName);
}

std::list<std::string> CNfsConnection::GetExportList(const CURL &url)
std::list<std::string> CNfsConnection::GetExportList(const CURL& url)
{
std::list<std::string> retList;
std::list<std::string> retList;

struct exportnode *exportlist, *tmp;
exportlist = mount_getexports(m_resolvedHostName.c_str());
tmp = exportlist;
struct exportnode *exportlist, *tmp;
#ifdef HAS_NFS_MOUNT_GETEXPORTS_TIMEOUT
exportlist = mount_getexports_timeout(
m_resolvedHostName.c_str(),
CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_nfsTimeout * 1000);
#else
exportlist = mount_getexports(m_resolvedHostName.c_str());
#endif
tmp = exportlist;

for(tmp = exportlist; tmp!=NULL; tmp=tmp->ex_next)
{
std::string exportStr = std::string(tmp->ex_dir);
for (tmp = exportlist; tmp != NULL; tmp = tmp->ex_next)
{
std::string exportStr = std::string(tmp->ex_dir);

retList.push_back(exportStr);
}
retList.push_back(exportStr);
}

mount_free_export_list(exportlist);
retList.sort();
retList.reverse();
mount_free_export_list(exportlist);
retList.sort();
retList.reverse();

return retList;
return retList;
}

void CNfsConnection::clearMembers()
Expand Down Expand Up @@ -181,6 +187,7 @@ int CNfsConnection::getContextForExport(const std::string &exportname)
{
struct contextTimeout tmp;
CSingleLock lock(openContextLock);
setTimeout(m_pNfsContext);
tmp.pContext = m_pNfsContext;
tmp.lastAccessedTime = XbmcThreads::SystemClockMillis();
m_openContextMap[exportname] = tmp; //add context to list of all contexts
Expand Down Expand Up @@ -426,6 +433,7 @@ int CNfsConnection::stat(const CURL &url, NFSSTAT *statbuff)

if(pTmpContext)
{
setTimeout(pTmpContext);
//we connect to the directory of the path. This will be the "root" path of this connection then.
//So all fileoperations are relative to this mountpoint...
nfsRet = nfs_mount(pTmpContext, m_resolvedHostName.c_str(), exportPath.c_str());
Expand Down Expand Up @@ -465,6 +473,15 @@ void CNfsConnection::AddIdleConnection()
m_IdleTimeout = 180;
}


void CNfsConnection::setTimeout(struct nfs_context* context)
{
#ifdef HAS_NFS_SET_TIMEOUT
uint32_t timeout = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_nfsTimeout;
nfs_set_timeout(context, timeout > 0 ? timeout * 1000 : -1);
#endif
}

CNfsConnection gNfsConnection;

CNFSFile::CNFSFile()
Expand Down Expand Up @@ -589,7 +606,7 @@ int CNFSFile::Stat(const CURL& url, struct __stat64* buffer)
{
if(buffer)
{
#if defined(TARGET_WINDOWS)//! @todo get rid of this define after gotham v13
#if defined(TARGET_WINDOWS) //! @todo get rid of this define after gotham v13
memcpy(buffer, &tmpBuffer, sizeof(struct __stat64));
#else
memset(buffer, 0, sizeof(struct __stat64));
Expand Down
1 change: 1 addition & 0 deletions xbmc/filesystem/NFSFile.h
Expand Up @@ -95,6 +95,7 @@ class CNfsConnection : public CCriticalSection
void destroyContext(const std::string &exportName);
void resolveHost(const CURL &url);//resolve hostname by dnslookup
void keepAlive(std::string _exportPath, struct nfsfh *_pFileHandle);
static void setTimeout(struct nfs_context* context);
};

extern CNfsConnection gNfsConnection;
Expand Down
10 changes: 10 additions & 0 deletions xbmc/settings/AdvancedSettings.cpp
Expand Up @@ -421,6 +421,8 @@ void CAdvancedSettings::Initialize()

m_userAgent = g_sysinfo.GetUserAgent();

m_nfsTimeout = 5;

m_initialized = true;
}

Expand Down Expand Up @@ -501,6 +503,14 @@ void CAdvancedSettings::ParseSettingsFile(const std::string &file)
passTag->LinkEndChild(new TiXmlText("*****"));
}
}
if (network->FirstChildElement("nfstimeout"))
{
#ifdef HAS_NFS_SET_TIMEOUT
XMLUtils::GetUInt(network, "nfstimeout", m_nfsTimeout, 0, 3600);
#else
CLog::Log(LOGWARNING, "nfstimeout unsupported");
#endif
}
}

// Dump contents of copied AS.xml to debug log
Expand Down
1 change: 1 addition & 0 deletions xbmc/settings/AdvancedSettings.h
Expand Up @@ -365,6 +365,7 @@ class CAdvancedSettings : public ISettingCallback, public ISettingsHandler
bool m_openGlDebugging;

std::string m_userAgent;
uint32_t m_nfsTimeout;

private:
void Initialize();
Expand Down

0 comments on commit e6bbaf0

Please sign in to comment.