In os_unix.c, do not open the directory containing the database file when
the database file is opened. Instead, wait until time to fsync() the directory. And do not report an error if the open fails, since some systems (Ex: AIX and a chromium sandbox) are unable to open and fsync directories. FossilOrigin-Name: 713b1b7dc1296e9cee42aeaad8c85528155f721d
This commit is contained in:
parent
036ac7fa90
commit
0059eae367
12
manifest
12
manifest
@ -1,5 +1,5 @@
|
||||
C Allow\sthe\sunlink()\ssystem\scall\sto\sbe\soverridden\sin\sos_unix.c.
|
||||
D 2011-08-08T23:18:05.791
|
||||
C In\sos_unix.c,\sdo\snot\sopen\sthe\sdirectory\scontaining\sthe\sdatabase\sfile\swhen\nthe\sdatabase\sfile\sis\sopened.\s\sInstead,\swait\suntil\stime\sto\sfsync()\sthe\ndirectory.\s\sAnd\sdo\snot\sreport\san\serror\sif\sthe\sopen\sfails,\ssince\ssome\nsystems\s(Ex:\sAIX\sand\sa\schromium\ssandbox)\sare\sunable\sto\sopen\sand\sfsync\ndirectories.
|
||||
D 2011-08-08T23:48:40.886
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 1e6988b3c11dee9bd5edc0c804bd4468d74a9cdc
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -165,7 +165,7 @@ F src/os.c fcc717427a80b2ed225373f07b642dc1aad7490b
|
||||
F src/os.h 9dbed8c2b9c1f2f2ebabc09e49829d4777c26bf9
|
||||
F src/os_common.h 65a897143b64667d23ed329a7984b9b405accb58
|
||||
F src/os_os2.c 4a75888ba3dfc820ad5e8177025972d74d7f2440
|
||||
F src/os_unix.c 597c854d9428b547717bcc9d2fc885a8030d7f86
|
||||
F src/os_unix.c d059bd9c8b72b41316d6af803cac6a0501fa0a43
|
||||
F src/os_win.c 4eb6fa00ee28f6d7bad0526edcbe5a60d297c67a
|
||||
F src/pager.c 120550e7ef01dafaa2cbb4a0528c0d87c8f12b41
|
||||
F src/pager.h 3f8c783de1d4706b40b1ac15b64f5f896bcc78d1
|
||||
@ -955,7 +955,7 @@ F tool/symbols.sh caaf6ccc7300fd43353318b44524853e222557d5
|
||||
F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
F tool/warnings.sh 2ebae31e1eb352696f3c2f7706a34c084b28c262
|
||||
P 3c8f97ae527e380bf2583c7cf8ceac9509f29bfe
|
||||
R 88d01aec65e2a86c5fc8acbdba857107
|
||||
P 8d1b5c3ac027ac00d57a250aad45230a09645617
|
||||
R 0f87b14e27e19fe9ccf3a0f4bda64412
|
||||
U drh
|
||||
Z 304dbede0b6b9e99a78b17b48d6b9a6b
|
||||
Z 78ef8639c983997441ad2d451ca4d175
|
||||
|
@ -1 +1 @@
|
||||
8d1b5c3ac027ac00d57a250aad45230a09645617
|
||||
713b1b7dc1296e9cee42aeaad8c85528155f721d
|
138
src/os_unix.c
138
src/os_unix.c
@ -208,7 +208,6 @@ struct unixFile {
|
||||
sqlite3_io_methods const *pMethod; /* Always the first entry */
|
||||
unixInodeInfo *pInode; /* Info about locks on this inode */
|
||||
int h; /* The file descriptor */
|
||||
int dirfd; /* File descriptor for the directory */
|
||||
unsigned char eFileLock; /* The type of lock held on this fd */
|
||||
unsigned char ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */
|
||||
int lastErrno; /* The unix errno from last I/O error */
|
||||
@ -253,6 +252,7 @@ struct unixFile {
|
||||
#define UNIXFILE_EXCL 0x01 /* Connections from one process only */
|
||||
#define UNIXFILE_RDONLY 0x02 /* Connection is read only */
|
||||
#define UNIXFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */
|
||||
#define UNIXFILE_DIRSYNC 0x08 /* Directory sync needed */
|
||||
|
||||
/*
|
||||
** Include code that is common to all os_*.c files
|
||||
@ -1753,10 +1753,6 @@ static int unixUnlock(sqlite3_file *id, int eFileLock){
|
||||
*/
|
||||
static int closeUnixFile(sqlite3_file *id){
|
||||
unixFile *pFile = (unixFile*)id;
|
||||
if( pFile->dirfd>=0 ){
|
||||
robust_close(pFile, pFile->dirfd, __LINE__);
|
||||
pFile->dirfd=-1;
|
||||
}
|
||||
if( pFile->h>=0 ){
|
||||
robust_close(pFile, pFile->h, __LINE__);
|
||||
pFile->h = -1;
|
||||
@ -3249,6 +3245,37 @@ static int full_fsync(int fd, int fullSync, int dataOnly){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Open a file descriptor to the directory containing file zFilename.
|
||||
** If successful, *pFd is set to the opened file descriptor and
|
||||
** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM
|
||||
** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined
|
||||
** value.
|
||||
**
|
||||
** If SQLITE_OK is returned, the caller is responsible for closing
|
||||
** the file descriptor *pFd using close().
|
||||
*/
|
||||
static int openDirectory(const char *zFilename, int *pFd){
|
||||
int ii;
|
||||
int fd = -1;
|
||||
char zDirname[MAX_PATHNAME+1];
|
||||
|
||||
sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename);
|
||||
for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--);
|
||||
if( ii>0 ){
|
||||
zDirname[ii] = '\0';
|
||||
fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0);
|
||||
if( fd>=0 ){
|
||||
#ifdef FD_CLOEXEC
|
||||
osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
|
||||
#endif
|
||||
OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname));
|
||||
}
|
||||
}
|
||||
*pFd = fd;
|
||||
return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname));
|
||||
}
|
||||
|
||||
/*
|
||||
** Make sure all writes to a particular file are committed to disk.
|
||||
**
|
||||
@ -3289,28 +3316,22 @@ static int unixSync(sqlite3_file *id, int flags){
|
||||
pFile->lastErrno = errno;
|
||||
return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath);
|
||||
}
|
||||
if( pFile->dirfd>=0 ){
|
||||
OSTRACE(("DIRSYNC %-3d (have_fullfsync=%d fullsync=%d)\n", pFile->dirfd,
|
||||
|
||||
/* Also fsync the directory containing the file if the DIRSYNC flag
|
||||
** is set. This is a one-time occurrance. Many systems (examples: AIX
|
||||
** or any process running inside a chromium sandbox) are unable to fsync a
|
||||
** directory, so ignore errors.
|
||||
*/
|
||||
if( pFile->ctrlFlags & UNIXFILE_DIRSYNC ){
|
||||
int dirfd;
|
||||
OSTRACE(("DIRSYNC %s (have_fullfsync=%d fullsync=%d)\n", pFile->zPath,
|
||||
HAVE_FULLFSYNC, isFullsync));
|
||||
#ifndef SQLITE_DISABLE_DIRSYNC
|
||||
/* The directory sync is only attempted if full_fsync is
|
||||
** turned off or unavailable. If a full_fsync occurred above,
|
||||
** then the directory sync is superfluous.
|
||||
*/
|
||||
if( (!HAVE_FULLFSYNC || !isFullsync) && full_fsync(pFile->dirfd,0,0) ){
|
||||
/*
|
||||
** We have received multiple reports of fsync() returning
|
||||
** errors when applied to directories on certain file systems.
|
||||
** A failed directory sync is not a big deal. So it seems
|
||||
** better to ignore the error. Ticket #1657
|
||||
*/
|
||||
/* pFile->lastErrno = errno; */
|
||||
/* return SQLITE_IOERR; */
|
||||
openDirectory(pFile->zPath, &dirfd);
|
||||
if( dirfd>=0 ){
|
||||
full_fsync(dirfd, 0, 0);
|
||||
robust_close(pFile, dirfd, __LINE__);
|
||||
}
|
||||
#endif
|
||||
/* Only need to sync once, so close the directory when we are done */
|
||||
robust_close(pFile, pFile->dirfd, __LINE__);
|
||||
pFile->dirfd = -1;
|
||||
pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@ -4478,7 +4499,7 @@ typedef const sqlite3_io_methods *(*finder_type)(const char*,unixFile*);
|
||||
static int fillInUnixFile(
|
||||
sqlite3_vfs *pVfs, /* Pointer to vfs object */
|
||||
int h, /* Open file descriptor of file being opened */
|
||||
int dirfd, /* Directory file descriptor */
|
||||
int syncDir, /* True to sync directory on first sync */
|
||||
sqlite3_file *pId, /* Write to the unixFile structure here */
|
||||
const char *zFilename, /* Name of the file being opened */
|
||||
int noLock, /* Omit locking if true */
|
||||
@ -4509,7 +4530,6 @@ static int fillInUnixFile(
|
||||
|
||||
OSTRACE(("OPEN %-3d %s\n", h, zFilename));
|
||||
pNew->h = h;
|
||||
pNew->dirfd = dirfd;
|
||||
pNew->zPath = zFilename;
|
||||
if( memcmp(pVfs->zName,"unix-excl",10)==0 ){
|
||||
pNew->ctrlFlags = UNIXFILE_EXCL;
|
||||
@ -4519,6 +4539,9 @@ static int fillInUnixFile(
|
||||
if( isReadOnly ){
|
||||
pNew->ctrlFlags |= UNIXFILE_RDONLY;
|
||||
}
|
||||
if( syncDir ){
|
||||
pNew->ctrlFlags |= UNIXFILE_DIRSYNC;
|
||||
}
|
||||
|
||||
#if OS_VXWORKS
|
||||
pNew->pId = vxworksFindFileId(zFilename);
|
||||
@ -4651,7 +4674,6 @@ static int fillInUnixFile(
|
||||
pNew->isDelete = isDelete;
|
||||
#endif
|
||||
if( rc!=SQLITE_OK ){
|
||||
if( dirfd>=0 ) robust_close(pNew, dirfd, __LINE__);
|
||||
if( h>=0 ) robust_close(pNew, h, __LINE__);
|
||||
}else{
|
||||
pNew->pMethod = pLockingStyle;
|
||||
@ -4660,37 +4682,6 @@ static int fillInUnixFile(
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Open a file descriptor to the directory containing file zFilename.
|
||||
** If successful, *pFd is set to the opened file descriptor and
|
||||
** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM
|
||||
** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined
|
||||
** value.
|
||||
**
|
||||
** If SQLITE_OK is returned, the caller is responsible for closing
|
||||
** the file descriptor *pFd using close().
|
||||
*/
|
||||
static int openDirectory(const char *zFilename, int *pFd){
|
||||
int ii;
|
||||
int fd = -1;
|
||||
char zDirname[MAX_PATHNAME+1];
|
||||
|
||||
sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename);
|
||||
for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--);
|
||||
if( ii>0 ){
|
||||
zDirname[ii] = '\0';
|
||||
fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0);
|
||||
if( fd>=0 ){
|
||||
#ifdef FD_CLOEXEC
|
||||
osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
|
||||
#endif
|
||||
OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname));
|
||||
}
|
||||
}
|
||||
*pFd = fd;
|
||||
return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname));
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the name of a directory in which to put temporary files.
|
||||
** If no suitable temporary file directory can be found, return NULL.
|
||||
@ -4923,7 +4914,6 @@ static int unixOpen(
|
||||
){
|
||||
unixFile *p = (unixFile *)pFile;
|
||||
int fd = -1; /* File descriptor returned by open() */
|
||||
int dirfd = -1; /* Directory file descriptor */
|
||||
int openFlags = 0; /* Flags to pass to open() */
|
||||
int eType = flags&0xFFFFFF00; /* Type of file to open */
|
||||
int noLock; /* True to omit locking primitives */
|
||||
@ -4942,7 +4932,7 @@ static int unixOpen(
|
||||
** a file-descriptor on the directory too. The first time unixSync()
|
||||
** is called the directory file descriptor will be fsync()ed and close()d.
|
||||
*/
|
||||
int isOpenDirectory = (isCreate && (
|
||||
int syncDir = (isCreate && (
|
||||
eType==SQLITE_OPEN_MASTER_JOURNAL
|
||||
|| eType==SQLITE_OPEN_MAIN_JOURNAL
|
||||
|| eType==SQLITE_OPEN_WAL
|
||||
@ -4996,7 +4986,7 @@ static int unixOpen(
|
||||
p->pUnused = pUnused;
|
||||
}else if( !zName ){
|
||||
/* If zName is NULL, the upper layer is requesting a temp file. */
|
||||
assert(isDelete && !isOpenDirectory);
|
||||
assert(isDelete && !syncDir);
|
||||
rc = unixGetTempname(MAX_PATHNAME+1, zTmpname);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
@ -5061,19 +5051,6 @@ static int unixOpen(
|
||||
}
|
||||
#endif
|
||||
|
||||
if( isOpenDirectory ){
|
||||
rc = openDirectory(zPath, &dirfd);
|
||||
if( rc!=SQLITE_OK ){
|
||||
/* It is safe to close fd at this point, because it is guaranteed not
|
||||
** to be open on a database file. If it were open on a database file,
|
||||
** it would not be safe to close as this would release any locks held
|
||||
** on the file by this process. */
|
||||
assert( eType!=SQLITE_OPEN_MAIN_DB );
|
||||
robust_close(p, fd, __LINE__);
|
||||
goto open_finished;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FD_CLOEXEC
|
||||
osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
|
||||
#endif
|
||||
@ -5085,7 +5062,6 @@ static int unixOpen(
|
||||
struct statfs fsInfo;
|
||||
if( fstatfs(fd, &fsInfo) == -1 ){
|
||||
((unixFile*)pFile)->lastErrno = errno;
|
||||
if( dirfd>=0 ) robust_close(p, dirfd, __LINE__);
|
||||
robust_close(p, fd, __LINE__);
|
||||
return SQLITE_IOERR_ACCESS;
|
||||
}
|
||||
@ -5117,9 +5093,6 @@ static int unixOpen(
|
||||
** not while other file descriptors opened by the same process on
|
||||
** the same file are working. */
|
||||
p->lastErrno = errno;
|
||||
if( dirfd>=0 ){
|
||||
robust_close(p, dirfd, __LINE__);
|
||||
}
|
||||
robust_close(p, fd, __LINE__);
|
||||
rc = SQLITE_IOERR_ACCESS;
|
||||
goto open_finished;
|
||||
@ -5127,7 +5100,7 @@ static int unixOpen(
|
||||
useProxy = !(fsInfo.f_flags&MNT_LOCAL);
|
||||
}
|
||||
if( useProxy ){
|
||||
rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock,
|
||||
rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock,
|
||||
isDelete, isReadonly);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:");
|
||||
@ -5145,7 +5118,7 @@ static int unixOpen(
|
||||
}
|
||||
#endif
|
||||
|
||||
rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock,
|
||||
rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock,
|
||||
isDelete, isReadonly);
|
||||
open_finished:
|
||||
if( rc!=SQLITE_OK ){
|
||||
@ -5745,7 +5718,6 @@ static int proxyCreateUnixFile(
|
||||
int islockfile /* if non zero missing dirs will be created */
|
||||
) {
|
||||
int fd = -1;
|
||||
int dirfd = -1;
|
||||
unixFile *pNew;
|
||||
int rc = SQLITE_OK;
|
||||
int openFlags = O_RDWR | O_CREAT;
|
||||
@ -5810,7 +5782,7 @@ static int proxyCreateUnixFile(
|
||||
pUnused->flags = openFlags;
|
||||
pNew->pUnused = pUnused;
|
||||
|
||||
rc = fillInUnixFile(&dummyVfs, fd, dirfd, (sqlite3_file*)pNew, path, 0, 0, 0);
|
||||
rc = fillInUnixFile(&dummyVfs, fd, 0, (sqlite3_file*)pNew, path, 0, 0, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
*ppFile = pNew;
|
||||
return SQLITE_OK;
|
||||
|
Loading…
x
Reference in New Issue
Block a user