diff options
author | Mark H Weaver <mhw@netris.org> | 2014-04-02 12:14:46 -0400 |
---|---|---|
committer | Mark H Weaver <mhw@netris.org> | 2014-04-02 15:31:28 -0400 |
commit | 8ead71b4b03a888d846c7b7c5bbc3addc8013df7 (patch) | |
tree | ad92d321363a862418a9f91343946789123f3e34 /gnu | |
parent | d6a601816fd5b254d99f0c11127388b46ce234ae (diff) | |
download | gnu-guix-8ead71b4b03a888d846c7b7c5bbc3addc8013df7.tar gnu-guix-8ead71b4b03a888d846c7b7c5bbc3addc8013df7.tar.gz |
gnu: sqlite: Fix sqlite on systems with page size larger than 32K.
Based on a patch by Dan Kennedy <danielk1977@gmail.com>.
* gnu/packages/patches/sqlite-large-page-size-fix.patch: New file.
* gnu/packages/sqlite.scm (sqlite): Add it.
* gnu-system.am (dist_patch_DATA): Add it.
Diffstat (limited to 'gnu')
-rw-r--r-- | gnu/packages/patches/sqlite-large-page-size-fix.patch | 180 | ||||
-rw-r--r-- | gnu/packages/sqlite.scm | 4 |
2 files changed, 183 insertions, 1 deletions
diff --git a/gnu/packages/patches/sqlite-large-page-size-fix.patch b/gnu/packages/patches/sqlite-large-page-size-fix.patch new file mode 100644 index 0000000000..c561fa20a2 --- /dev/null +++ b/gnu/packages/patches/sqlite-large-page-size-fix.patch @@ -0,0 +1,180 @@ +Add an experimental fix to avoid attempting to mmap memory from an +offset that is not a multiple of the system page size on systems with +page sizes larger than 32KB. + +Patch by Dan Kennedy <danielk1977@gmail.com>. + +--- sqlite-autoconf/sqlite3.c.orig 2014-03-22 23:44:47.055908203 -0400 ++++ sqlite-autoconf/sqlite3.c 2014-03-22 23:44:06.716552734 -0400 +@@ -24010,6 +24010,7 @@ + + /* Forward reference */ + static int openDirectory(const char*, int*); ++static int unixGetpagesize(void); + + /* + ** Many system calls are accessed through pointer-to-functions so that +@@ -24133,6 +24134,9 @@ + #define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[23].pCurrent) + #endif + ++ { "getpagesize", (sqlite3_syscall_ptr)unixGetpagesize, 0 }, ++#define osGetpagesize ((int(*)(void))aSyscall[24].pCurrent) ++ + }; /* End of the overrideable system calls */ + + /* +@@ -27792,6 +27796,36 @@ + return rc; + } + ++/* ++** Return the system page size. ++** ++** This function should not be called directly by other code in this file. ++** Instead, it should be called via macro osGetpagesize(). ++*/ ++static int unixGetpagesize(void){ ++#if defined(_BSD_SOURCE) ++ return getpagesize(); ++#else ++ return (int)sysconf(_SC_PAGESIZE); ++#endif ++} ++ ++/* ++** Return the minimum number of 32KB shm regions that should be mapped at ++** a time, assuming that each mapping must be an integer multiple of the ++** current system page-size. ++** ++** Usually, this is 1. The exception seems to be systems that are configured ++** to use 64KB pages - in this case each mapping must cover at least two ++** shm regions. ++*/ ++static int unixShmRegionPerMap(void){ ++ int shmsz = 32*1024; /* SHM region size */ ++ int pgsz = osGetpagesize(); /* System page size */ ++ assert( ((pgsz-1)&pgsz)==0 ); /* Page size must be a power of 2 */ ++ if( pgsz<shmsz ) return 1; ++ return pgsz/shmsz; ++} + + /* + ** Purge the unixShmNodeList list of all entries with unixShmNode.nRef==0. +@@ -27803,10 +27837,11 @@ + unixShmNode *p = pFd->pInode->pShmNode; + assert( unixMutexHeld() ); + if( p && p->nRef==0 ){ ++ int nShmPerMap = unixShmRegionPerMap(); + int i; + assert( p->pInode==pFd->pInode ); + sqlite3_mutex_free(p->mutex); +- for(i=0; i<p->nRegion; i++){ ++ for(i=0; i<p->nRegion; i+=nShmPerMap){ + if( p->h>=0 ){ + osMunmap(p->apRegion[i], p->szRegion); + }else{ +@@ -28013,6 +28048,8 @@ + unixShm *p; + unixShmNode *pShmNode; + int rc = SQLITE_OK; ++ int nShmPerMap = unixShmRegionPerMap(); ++ int nReqRegion; + + /* If the shared-memory file has not yet been opened, open it now. */ + if( pDbFd->pShm==0 ){ +@@ -28028,9 +28065,12 @@ + assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 ); + assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 ); + +- if( pShmNode->nRegion<=iRegion ){ ++ /* Minimum number of regions required to be mapped. */ ++ nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap; ++ ++ if( pShmNode->nRegion<nReqRegion ){ + char **apNew; /* New apRegion[] array */ +- int nByte = (iRegion+1)*szRegion; /* Minimum required file size */ ++ int nByte = nReqRegion*szRegion; /* Minimum required file size */ + struct stat sStat; /* Used by fstat() */ + + pShmNode->szRegion = szRegion; +@@ -28079,17 +28119,19 @@ + + /* Map the requested memory region into this processes address space. */ + apNew = (char **)sqlite3_realloc( +- pShmNode->apRegion, (iRegion+1)*sizeof(char *) ++ pShmNode->apRegion, nReqRegion*sizeof(char *) + ); + if( !apNew ){ + rc = SQLITE_IOERR_NOMEM; + goto shmpage_out; + } + pShmNode->apRegion = apNew; +- while(pShmNode->nRegion<=iRegion){ ++ while( pShmNode->nRegion<nReqRegion ){ ++ int nMap = szRegion*nShmPerMap; ++ int i; + void *pMem; + if( pShmNode->h>=0 ){ +- pMem = osMmap(0, szRegion, ++ pMem = osMmap(0, nMap, + pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE, + MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion + ); +@@ -28105,8 +28147,11 @@ + } + memset(pMem, 0, szRegion); + } +- pShmNode->apRegion[pShmNode->nRegion] = pMem; +- pShmNode->nRegion++; ++ ++ for(i=0; i<nShmPerMap; i++){ ++ pShmNode->apRegion[pShmNode->nRegion+i] = &((char*)pMem)[szRegion*i]; ++ } ++ pShmNode->nRegion += nShmPerMap; + } + } + +@@ -28321,19 +28366,6 @@ + } + + /* +-** Return the system page size. +-*/ +-static int unixGetPagesize(void){ +-#if HAVE_MREMAP +- return 512; +-#elif defined(_BSD_SOURCE) +- return getpagesize(); +-#else +- return (int)sysconf(_SC_PAGESIZE); +-#endif +-} +- +-/* + ** Attempt to set the size of the memory mapping maintained by file + ** descriptor pFd to nNew bytes. Any existing mapping is discarded. + ** +@@ -28369,8 +28401,12 @@ + if( (pFd->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE; + + if( pOrig ){ +- const int szSyspage = unixGetPagesize(); ++#if HAVE_MREMAP ++ i64 nReuse = pFd->mmapSize; ++#else ++ const int szSyspage = osGetpagesize(); + i64 nReuse = (pFd->mmapSize & ~(szSyspage-1)); ++#endif + u8 *pReq = &pOrig[nReuse]; + + /* Unmap any pages of the existing mapping that cannot be reused. */ +@@ -31116,7 +31152,7 @@ + + /* Double-check that the aSyscall[] array has been constructed + ** correctly. See ticket [bb3a86e890c8e96ab] */ +- assert( ArraySize(aSyscall)==24 ); ++ assert( ArraySize(aSyscall)==25 ); + + /* Register all VFSes defined in the aVfs[] array */ + for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ diff --git a/gnu/packages/sqlite.scm b/gnu/packages/sqlite.scm index 5b6a96f4b0..0475b6c77e 100644 --- a/gnu/packages/sqlite.scm +++ b/gnu/packages/sqlite.scm @@ -49,7 +49,9 @@ "/sqlite-autoconf-" numeric-version ".tar.gz"))) (sha256 (base32 - "19gicv5vdi5c0p8shr1bmihldj409aqz3r4wr7d3pwb6xf1xv4p4")))) + "19gicv5vdi5c0p8shr1bmihldj409aqz3r4wr7d3pwb6xf1xv4p4")) + (patches + (list (search-patch "sqlite-large-page-size-fix.patch"))))) (build-system gnu-build-system) (home-page "http://www.sqlite.org/") (synopsis "The SQLite database management system") |