00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <eyedbconfig.h>
00025
00026 #include <sys/types.h>
00027
00028 #include "kern_p.h"
00029
00030
00031
00032 #define ABS(x) ((off_t)( (long long)(x) > 0 ? (long long)(x) : -(long long)(x) ))
00033 #define DIST(MMD, s, e) ABS((MMD)->s_start - (s))
00034 #define IS_IN(x,y,z) ( (x) >= (y) && (x) < (z) )
00035
00036
00037
00038
00039
00040
00041 namespace eyedbsm {
00042
00043 void
00044 hdl_release(MmapH *hdl)
00045 {
00046 MmapDesc *mmd = hdl->mmd;
00047
00048 if (mmd && mmd->locked)
00049 {
00050
00051 mmd->pts[hdl->pos] = 0;
00052 *hdl->pt = 0;
00053 if (!--mmd->npts)
00054 {
00055 mmd->locked = False;
00056 m_unlock(mmd->m);
00057 }
00058 }
00059 }
00060
00061
00062 static void
00063 garb_trig(void *arg)
00064 {
00065 MmapDesc *mmd = (MmapDesc *)arg;
00066 #ifdef TRACE
00067 utlog("garb_trig %x mapaddr 0x%x %d\n", mmd, mmd->mapaddr, mmd->locked);
00068 #endif
00069 ESM_ASSERT_ABORT(!mmd->locked, 0, 0);
00070 mmd->ismapped = False;
00071 mmd->ref = 0;
00072 mmd->locked = False;
00073 }
00074
00075 static void display_dmd(DatDesc *dmd)
00076 {
00077 MmapDesc *mmd, *mmd1, *fmmd = 0, *mmend = &dmd->mmd[MAX_MMAP_SEGMENTS];
00078
00079 unsigned int n = 0;
00080 for (mmd = dmd->mmd; mmd < mmend; mmd++, n++) {
00081 if (mmd->ismapped) {
00082 fprintf(stdout, "segment #%u %llx - %llx (%s)\n", n, mmd->s_start, mmd->s_end,
00083 mmd->locked ? "locked" : "not locked");
00084 }
00085 }
00086 }
00087
00088 static void check_dmd(DatDesc *dmd)
00089 {
00090 MmapDesc *mmd, *mmd1, *fmmd = 0, *mmend = &dmd->mmd[MAX_MMAP_SEGMENTS];
00091 unsigned int n;
00092
00093 bool should_display = false;
00094 for (mmd = dmd->mmd, n = 0; mmd < mmend; mmd++, n++) {
00095 if (mmd->ismapped) {
00096 off_t ws_start = mmd->s_start, ws_end = mmd->s_end;
00097 unsigned int m = n + 1;
00098 for (mmd1 = dmd->mmd + m; mmd1 < mmend; mmd1++, m++) {
00099 if (mmd1->ismapped) {
00100 #if 1
00101 if (IS_IN(ws_start, mmd1->s_start, mmd1->s_end)) {
00102 fprintf(stdout, "multimap segment #%u start: %llx in #%u %llx - %llx (%s)\n", n, ws_start, m, mmd1->s_start, mmd1->s_end, mmd1->locked ? "locked" : "not locked");
00103 should_display = true;
00104 }
00105
00106 if (IS_IN(ws_end-1, mmd1->s_start, mmd1->s_end)) {
00107 fprintf(stdout, "multimap segment #%u end: %llx in #%u %llx - %llx (%s)\n", n, ws_end, m, mmd1->s_start, mmd1->s_end, mmd1->locked ? "locked" : "not locked");
00108 should_display = true;
00109 }
00110 #else
00111 ESM_ASSERT_ABORT(!IS_IN(ws_start, mmd1->s_start, mmd1->s_end), 0, 0);
00112 ESM_ASSERT_ABORT(!IS_IN(ws_end-1, mmd1->s_start, mmd1->s_end), 0, 0);
00113 #endif
00114 }
00115 }
00116 }
00117 }
00118
00119 if (should_display)
00120 display_dmd(dmd);
00121 }
00122
00123 static MmapDesc *
00124 find_segment(register DatDesc *dmd, off_t ws_start, off_t ws_end)
00125 {
00126 off_t delta = 0, uv;
00127 unsigned long ref = curref+1;
00128
00129 MmapDesc *mmd, *fmmd = 0, *mmend = &dmd->mmd[MAX_MMAP_SEGMENTS];
00130
00131 for (mmd = dmd->mmd; mmd < mmend; mmd++) {
00132 if (mmd->ismapped && !mmd->locked) {
00133 if (mmd->ref < ref)
00134 if ((uv = DIST(mmd, ws_start, ws_end)) > delta) {
00135 ref = mmd->ref;
00136 fmmd = mmd;
00137 }
00138 }
00139 }
00140
00141 ESM_ASSERT_ABORT(fmmd, 0, 0);
00142
00143 SEGMENT_UNMAP(fmmd);
00144 return fmmd;
00145 }
00146
00147 static void stop_it_man() {}
00148
00149 static int
00150 mmd_add(MmapDesc *mmd, char **pt)
00151 {
00152 char ***p;
00153 int pos;
00154
00155 if (mmd->npts >= mmd->nalloc) {
00156 int inc = 6;
00157 if (!mmd->nalloc) {
00158 mmd->nalloc = inc;
00159 mmd->pts = (char ***)m_calloc(sizeof(char **)*mmd->nalloc, 1);
00160 }
00161 else {
00162 mmd->nalloc += inc;
00163 mmd->pts = (char ***)m_realloc(mmd->pts, sizeof(char **)*mmd->nalloc);
00164 memset(mmd->pts+(mmd->nalloc-inc), 0, sizeof(char **)*inc);
00165 }
00166 }
00167
00168 for (p = mmd->pts, pos = 0; pos < mmd->nalloc; p++, pos++)
00169 if (!*p) {
00170 mmd->pts[pos] = pt;
00171 mmd->npts++;
00172 mmd->locked = True;
00173 assert(mmd->npts < 6);
00174
00175 return pos;
00176 }
00177 ESM_ASSERT_ABORT(0, 0, 0);
00178 }
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 char *
00193 oidloc2addr(const DbHandle *dbh, const OidLoc &oidloc,
00194 unsigned int size, char **pt, MmapH *hdl, int *up)
00195 {
00196 return slot2addr(dbh, oidloc.ns, oidloc.datid, size, pt, hdl, up);
00197 }
00198
00199 char *
00200 slot2addr(const DbHandle *dbh, off_t ws_start, short datid,
00201 unsigned int size, char **pt, MmapH *hdl, int *up)
00202 {
00203 ESM_ASSERT_ABORT(size > 0, 0, 0);
00204
00205 if (ws_start == (off_t) (-NS_OFFSET))
00206 return (char *)0;
00207
00208 MapHeader t_mp = DAT2MP(dbh, datid);
00209 MapHeader *mp = &t_mp;
00210 DatDesc *dmd = &dbh->vd->dmd[datid];
00211
00212 unsigned int sizeslot = x2h_u32(mp->sizeslot());
00213
00214 if (dmd->m_dat) {
00215 hdl->mmd = 0;
00216 if (up) *up = 0;
00217 return (char *)((ws_start * sizeslot) + dmd->addr);
00218 }
00219
00220 off_t delta_left = 0xffffffff, delta_right = 0xffffffff;
00221 MmapDesc *mmd, *mmend, *fmmd = 0, *mmd_left, *mmd_right;
00222 int fop, inc, inc1, v, wide, wide2, n;
00223 off_t startslot, ws_end, start, end, wa_start, wa_end, dum, uv,
00224 t_start, t_end;
00225 int nreloc=0;
00226 int pow2 = x2h_u32(mp->pow2());
00227 MmapDesc *mmd_reloc[MAX_MMAP_SEGMENTS];
00228 Mutex *mt = SLT_MTX(dbh);
00229 unsigned int xid = dbh->vd->xid;
00230 int x;
00231 Status status;
00232 TransactionContext *trctx = DBH2TRCTX(dbh);
00233
00234 ws_end = ws_start + (off_t)((size + sizeslot-1) >> pow2);
00235
00236 startslot = 0;
00237
00238 mmend = &dmd->mmd[MAX_MMAP_SEGMENTS];
00239
00240
00241 t_start = ws_start;
00242 t_end = ws_end;
00243
00244 try_again:
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 for (mmd = dmd->mmd; mmd < mmend; mmd++) {
00257 if (mmd->ismapped) {
00258 Boolean left = False, right = False;
00259
00260 if (IS_IN(t_start, mmd->s_start, mmd->s_end))
00261 left = True;
00262 if (IS_IN(t_end-1, mmd->s_start, mmd->s_end))
00263 right = True;
00264
00265 if (left && right) {
00266 mmd->ref = ++curref;
00267 m_access(mmd->m);
00268 hdl->mmd = mmd;
00269 hdl->pos = mmd_add(mmd, pt);
00270 hdl->pt = pt;
00271
00272
00273
00274
00275 if (up)
00276 *up = mmd->s_end;
00277 return (char *)(((ws_start - mmd->s_start) * sizeslot) +
00278 mmd->mapaddr);
00279 }
00280 else if (left || right) {
00281
00282 if (mmd->locked) {
00283 caddr_t t_addr = mmd->mapaddr;
00284 #ifdef TRACE1
00285 printf("should relocate really!\n");
00286 #endif
00287 mmd_reloc[nreloc++] = mmd;
00288 if (left)
00289 t_start = mmd->s_start;
00290 else if (right)
00291 t_end = mmd->s_end;
00292
00293 IDB_LOG(IDB_LOG_MMAP,
00294 ("slot2addr: interval cross segment [1]: must unmap\n"));
00295
00296 SEGMENT_UNMAP(mmd);
00297 mmd->mapaddr = t_addr;
00298
00299 mmd->locked = True;
00300
00301
00302
00303
00304
00305 IDB_LOG(IDB_LOG_MMAP, ("slot2addr: must try again\n"));
00306 goto try_again;
00307 }
00308 else {
00309 IDB_LOG(IDB_LOG_MMAP,
00310 ("slot2addr: interval cross segment [2]: must unmap\n"));
00311 SEGMENT_UNMAP(mmd);
00312 }
00313 }
00314 }
00315
00316 else if (!fmmd && !mmd->locked)
00317 fmmd = mmd;
00318 }
00319
00320
00321 if (!fmmd) {
00322 IDB_LOG(IDB_LOG_MMAP, ("slot2addr: no more segment available\n"));
00323 fmmd = find_segment(dmd, t_start, t_end);
00324 }
00325
00326
00327
00328
00329
00330 wide = dbh->vd->mapwide;
00331 wide2 = dbh->vd->mapwide2;
00332
00333
00334 wa_start = (t_start - startslot) * sizeslot;
00335 wa_end = (t_end - startslot) * sizeslot;
00336
00337
00338 wa_start = (wa_start/pgsize) * pgsize;
00339 wa_end = ((wa_end+pgsize-1)/pgsize) * pgsize;
00340
00341
00342
00343 mmd_left = mmd_right = 0;
00344 for (mmd = dmd->mmd; mmd < mmend; mmd++) {
00345 if (mmd->ismapped) {
00346 if ((long long)((uv = t_start - mmd->s_end)) >= 0 && uv < delta_left) {
00347 delta_left = uv;
00348 mmd_left = mmd;
00349 }
00350 if ((long long)((uv = mmd->s_start - t_end)) >= 0 && uv < delta_right) {
00351 delta_right = uv;
00352 mmd_right = mmd;
00353 }
00354 }
00355 }
00356
00357 if (!mmd_left) {
00358 if (((long long)(start = wa_start - wide2)) >= 0)
00359 inc = wide2;
00360 else {
00361 inc = 0;
00362 start = 0;
00363 }
00364 }
00365 else {
00366 off_t leftend = mmd_left->a_end;
00367 for (inc = wide2; inc >= 0; inc -= pgsize) {
00368 start = wa_start - inc;
00369 if (((long long)start) >= 0 && start >= leftend)
00370 break;
00371 }
00372
00373 ESM_ASSERT_ABORT(inc >= 0, mt, xid);
00374 }
00375
00376 if (!mmd_right)
00377 end = wa_end + wide - inc;
00378 else {
00379 off_t rightstart = mmd_right->a_start;
00380 for (inc1 = wide-inc; inc1 >= 0; inc1 -= pgsize) {
00381 end = wa_end + inc1;
00382 if (end <= rightstart)
00383 break;
00384 }
00385
00386 ESM_ASSERT_ABORT(inc1 >= 0, mt, xid);
00387 }
00388
00389 fop = ((dbh->vd->flags & VOLREAD) ? PROT_READ : PROT_READ|PROT_WRITE);
00390
00391 #ifdef TRACE1
00392 printf("%s: eyedbsm MMAP start=0x%x, end=0x%x, wa_start=0x%x, wa_end=0x%x, inc=0x%x, size=0x%x, ws_start=%d\n",
00393 get_time(), start, end, wa_start, wa_end, inc, size, ws_start);
00394 #endif
00395
00396 IDB_LOG(IDB_LOG_MMAP_DETAIL, ("slot2addr needs memory segment\n"));
00397 if (!(fmmd->m = m_mmap(0, end-start, fop, MAP_SHARED, dmd->fd,
00398 start, &fmmd->mapaddr, dmd->file, ws_start,
00399 ws_start+size-1))) {
00400
00401
00402
00403
00404 IDB_LOG(IDB_LOG_MMAP, ("slot2addr: m_mmap failed definitively in slot2addr %p\n",
00405 fmmd->m));
00406 return (char *)0;
00407 }
00408
00409 #ifdef TRACE1
00410 printf("mmapaddr 0x%x\n", fmmd->mapaddr);
00411 #endif
00412
00413 m_gtrig_set(fmmd->m, garb_trig, fmmd);
00414 m_lock(fmmd->m);
00415
00416 fmmd->a_start = start;
00417 fmmd->a_end = end;
00418 fmmd->s_start = (start>>pow2) + startslot;
00419 fmmd->s_end = (end>>pow2) + startslot;
00420 fmmd->ismapped = True;
00421
00422 hdl->mmd = fmmd;
00423 hdl->pos = mmd_add(fmmd, pt);
00424 hdl->pt = pt;
00425
00426 for (n = 0; n < nreloc; n++) {
00427 MmapDesc *mmd = mmd_reloc[n];
00428 char ***p;
00429 int cnt = mmd->npts, pos;
00430
00431 #ifdef TRACE1
00432 printf("mmd->npts %d\n", mmd->npts);
00433 #endif
00434
00435 for (p = mmd->pts, pos = 0; pos < mmd->nalloc; p++, pos++) {
00436 if (*p) {
00437 #ifdef TRACE1
00438 printf("must reloc 0x%x (0x%x) 0x%x\n", *p, **p,
00439 mmd->mapaddr);
00440 printf("START %d %d\n", mmd->s_start, fmmd->s_start);
00441 #endif
00442 if (mmd->s_start >= fmmd->s_start) {
00443 #ifdef TRACE1
00444 printf("hips!\n");
00445 #endif
00446
00447
00448
00449
00450
00451 **p = (char *)((mmd->s_start - fmmd->s_start) * sizeslot +
00452 (fmmd->mapaddr + (off_t)**p) -
00453 mmd->mapaddr);
00454 #ifdef TRACE1
00455 printf("after 0x%x\n", **p);
00456 #endif
00457 memset(mmd->pts, 0, sizeof(char **)*mmd->nalloc);
00458 mmd->npts = 0;
00459 mmd->locked = False;
00460 }
00461 if (!--cnt)
00462 break;
00463 }
00464 }
00465 }
00466
00467 #ifdef TRACE1
00468 printf("new mapped [%d]: %d %d %x %x (%x) %d\n", dmd->fd,
00469 fmmd->s_start, fmmd->s_end, start, end, fmmd, startslot);
00470 #endif
00471
00472
00473
00474 #if 0
00475 check_dmd(dmd);
00476 #endif
00477 fmmd->ref = ++curref;
00478
00479
00480
00481
00482
00483
00484
00485 if (up)
00486 *up = fmmd->s_end;
00487
00488 return (char *)(((ws_start - fmmd->s_start) * sizeslot) + fmmd->mapaddr);
00489 }
00490 }