From 8ead71b4b03a888d846c7b7c5bbc3addc8013df7 Mon Sep 17 00:00:00 2001 From: Mark H Weaver Date: Wed, 2 Apr 2014 12:14:46 -0400 Subject: gnu: sqlite: Fix sqlite on systems with page size larger than 32K. Based on a patch by Dan Kennedy . * 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. --- .../patches/sqlite-large-page-size-fix.patch | 180 +++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 gnu/packages/patches/sqlite-large-page-size-fix.patch (limited to 'gnu/packages/patches') 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 . + +--- 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( pgszpInode->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; inRegion; i++){ ++ for(i=0; inRegion; 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->nRegionszRegion = 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->nRegionh>=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; iapRegion[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++){ -- cgit 1.4.1