1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1997,2008 Oracle. All rights reserved. 5 * 6 * $Id: os_rw.c,v 12.28 2008/02/12 16:08:52 bostic Exp $ 7 */ 8 9#include "db_config.h" 10 11#include "db_int.h" 12 13/* 14 * __os_io -- 15 * Do an I/O. 16 */ 17int 18__os_io(env, op, fhp, pgno, pgsize, relative, io_len, buf, niop) 19 ENV *env; 20 int op; 21 DB_FH *fhp; 22 db_pgno_t pgno; 23 u_int32_t pgsize, relative, io_len; 24 u_int8_t *buf; 25 size_t *niop; 26{ 27 int ret; 28 29#ifndef DB_WINCE 30 if (__os_is_winnt()) { 31 DB_ENV *dbenv; 32 DWORD nbytes; 33 OVERLAPPED over; 34 ULONG64 off; 35 dbenv = env == NULL ? NULL : env->dbenv; 36 if ((off = relative) == 0) 37 off = (ULONG64)pgsize * pgno; 38 over.Offset = (DWORD)(off & 0xffffffff); 39 over.OffsetHigh = (DWORD)(off >> 32); 40 over.hEvent = 0; /* we don't want asynchronous notifications */ 41 42 if (dbenv != NULL && 43 FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS_ALL)) 44 __db_msg(env, 45 "fileops: %s %s: %lu bytes at offset %lu", 46 op == DB_IO_READ ? "read" : "write", 47 fhp->name, (u_long)io_len, (u_long)off); 48 49 LAST_PANIC_CHECK_BEFORE_IO(env); 50 51 switch (op) { 52 case DB_IO_READ: 53#if defined(HAVE_STATISTICS) 54 ++fhp->read_count; 55#endif 56 if (!ReadFile(fhp->handle, 57 buf, (DWORD)io_len, &nbytes, &over)) 58 goto slow; 59 break; 60 case DB_IO_WRITE: 61#ifdef HAVE_FILESYSTEM_NOTZERO 62 if (__os_fs_notzero()) 63 goto slow; 64#endif 65#if defined(HAVE_STATISTICS) 66 ++fhp->write_count; 67#endif 68 if (!WriteFile(fhp->handle, 69 buf, (DWORD)io_len, &nbytes, &over)) 70 goto slow; 71 break; 72 } 73 if (nbytes == io_len) { 74 *niop = (size_t)nbytes; 75 return (0); 76 } 77 } 78 79slow: 80#endif 81 MUTEX_LOCK(env, fhp->mtx_fh); 82 83 if ((ret = __os_seek(env, fhp, pgno, pgsize, relative)) != 0) 84 goto err; 85 86 switch (op) { 87 case DB_IO_READ: 88 ret = __os_read(env, fhp, buf, io_len, niop); 89 break; 90 case DB_IO_WRITE: 91 ret = __os_write(env, fhp, buf, io_len, niop); 92 break; 93 } 94 95err: MUTEX_UNLOCK(env, fhp->mtx_fh); 96 97 return (ret); 98} 99 100/* 101 * __os_read -- 102 * Read from a file handle. 103 */ 104int 105__os_read(env, fhp, addr, len, nrp) 106 ENV *env; 107 DB_FH *fhp; 108 void *addr; 109 size_t len; 110 size_t *nrp; 111{ 112 DB_ENV *dbenv; 113 DWORD count; 114 size_t offset, nr; 115 u_int8_t *taddr; 116 int ret; 117 118 dbenv = env == NULL ? NULL : env->dbenv; 119 ret = 0; 120 121#if defined(HAVE_STATISTICS) 122 ++fhp->read_count; 123#endif 124 if (dbenv != NULL && FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS_ALL)) 125 __db_msg(env, 126 "fileops: read %s: %lu bytes", fhp->name, (u_long)len); 127 128 for (taddr = addr, 129 offset = 0; offset < len; taddr += nr, offset += nr) { 130 LAST_PANIC_CHECK_BEFORE_IO(env); 131 RETRY_CHK((!ReadFile(fhp->handle, 132 taddr, (DWORD)(len - offset), &count, NULL)), ret); 133 if (count == 0 || ret != 0) 134 break; 135 nr = (size_t)count; 136 } 137 *nrp = taddr - (u_int8_t *)addr; 138 if (ret != 0) { 139 __db_syserr(env, ret, "read: 0x%lx, %lu", 140 P_TO_ULONG(taddr), (u_long)len - offset); 141 ret = __os_posix_err(ret); 142 } 143 return (ret); 144} 145 146/* 147 * __os_write -- 148 * Write to a file handle. 149 */ 150int 151__os_write(env, fhp, addr, len, nwp) 152 ENV *env; 153 DB_FH *fhp; 154 void *addr; 155 size_t len; 156 size_t *nwp; 157{ 158 int ret; 159 160#ifdef HAVE_FILESYSTEM_NOTZERO 161 /* Zero-fill as necessary. */ 162 if (__os_fs_notzero() && 163 (ret = __db_zero_fill(env, fhp)) != 0) 164 return (ret); 165#endif 166 return (__os_physwrite(env, fhp, addr, len, nwp)); 167} 168 169/* 170 * __os_physwrite -- 171 * Physical write to a file handle. 172 */ 173int 174__os_physwrite(env, fhp, addr, len, nwp) 175 ENV *env; 176 DB_FH *fhp; 177 void *addr; 178 size_t len; 179 size_t *nwp; 180{ 181 DB_ENV *dbenv; 182 DWORD count; 183 size_t offset, nw; 184 u_int8_t *taddr; 185 int ret; 186 187 dbenv = env == NULL ? NULL : env->dbenv; 188 ret = 0; 189 190#if defined(HAVE_STATISTICS) 191 ++fhp->write_count; 192#endif 193 if (dbenv != NULL && FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS_ALL)) 194 __db_msg(env, 195 "fileops: write %s: %lu bytes", fhp->name, (u_long)len); 196 197 for (taddr = addr, 198 offset = 0; offset < len; taddr += nw, offset += nw) { 199 LAST_PANIC_CHECK_BEFORE_IO(env); 200 RETRY_CHK((!WriteFile(fhp->handle, 201 taddr, (DWORD)(len - offset), &count, NULL)), ret); 202 if (ret != 0) 203 break; 204 nw = (size_t)count; 205 } 206 *nwp = len; 207 if (ret != 0) { 208 __db_syserr(env, ret, "write: %#lx, %lu", 209 P_TO_ULONG(taddr), (u_long)len - offset); 210 ret = __os_posix_err(ret); 211 212 DB_EVENT(env, DB_EVENT_WRITE_FAILED, NULL); 213 } 214 return (ret); 215} 216