]>
Commit | Line | Data |
---|---|---|
1d20bd4e JR |
1 | In certain cases with BerkleyDB 5.3.x we are getting the error: |
2 | ||
3 | db3.c:1443: dbcursor->pget(-30999): BDB0063 DB_BUFFER_SMALL: User memory too small for return value | |
4 | ||
5 | See https://bugs.launchpad.net/rpm/+bug/934420 for more information. | |
6 | ||
7 | It appears to be some type of a bug in the BerkleyDB 5.3.x. In an attempt | |
8 | to workaround the problem, when we encounter this situation we attempt | |
9 | to adjust the size of the mmap buffer until the call works, or we | |
1c15eec5 JR |
10 | end up trying 25 times. The new size is either the updated vp->size |
11 | from the failed pget call, or the previous size + 4096. | |
1d20bd4e JR |
12 | |
13 | If DBI debugging is enabled, additional diagnostics are printed, otherwise | |
14 | a basic retry and success message is added to show that the failure was | |
15 | resolved. | |
16 | ||
17 | Signed-off-by: Mark Hatle <mark.hatle@windriver.com> | |
18 | ||
19 | Index: rpm-5.4.9/rpmdb/rpmdb.c | |
20 | =================================================================== | |
21 | --- rpm-5.4.9.orig/rpmdb/rpmdb.c | |
22 | +++ rpm-5.4.9/rpmdb/rpmdb.c | |
23 | @@ -2212,8 +2212,12 @@ static int rpmmiGet(dbiIndex dbi, DBC * | |
24 | vp->flags |= DB_DBT_USERMEM; | |
25 | rc = dbiGet(dbi, dbcursor, kp, vp, flags); | |
26 | if (rc == DB_BUFFER_SMALL) { | |
27 | + int retry = 0; | |
28 | + size_t origlen = vp->size; | |
29 | size_t uhlen = vp->size; | |
30 | - void * uh = mmap(NULL, uhlen, _prot, _flags, _fdno, _off); | |
31 | + void * uh; | |
32 | +retry_get: | |
33 | + uh = mmap(NULL, uhlen, _prot, _flags, _fdno, _off); | |
34 | if (uh == NULL || uh == (void *)-1) | |
35 | fprintf(stderr, | |
36 | "==> mmap(%p[%u], 0x%x, 0x%x, %d, 0x%x) error(%d): %s\n", | |
37 | @@ -2235,6 +2239,25 @@ static int rpmmiGet(dbiIndex dbi, DBC * | |
38 | if (munmap(uh, uhlen) != 0) | |
39 | fprintf(stderr, "==> munmap(%p[%u]) error(%d): %s\n", | |
40 | uh, (unsigned)uhlen, errno, strerror(errno)); | |
41 | + /* We want to be sure to limit the number of retry attempts to avoid a loop! */ | |
1c15eec5 | 42 | + if (rc == DB_BUFFER_SMALL && retry < 25) { |
1d20bd4e | 43 | + /* If we got a largr vp-size back, use that, otherwise increment the size by 1k */ |
1c15eec5 | 44 | + uhlen = vp->size > uhlen ? vp->size : uhlen + 4096; |
1d20bd4e | 45 | + retry++; |
1c15eec5 | 46 | + if (_rpmmi_debug || (dbi)->dbi_debug) |
1d20bd4e JR |
47 | + fprintf(stderr, "==> DB_BUFFER_SMALL orig requested (%d), configured (%d), forcing larger buffer (%d), new size (%d)\n", |
48 | + origlen, vp->ulen, uhlen, vp->size); | |
49 | + else | |
076ab4d5 | 50 | + fprintf(stderr, "==> retry (%d) db3cpget (%d)\n", retry, uhlen); |
1d20bd4e JR |
51 | + goto retry_get; |
52 | + } | |
53 | + } | |
54 | + if (retry) { | |
1c15eec5 | 55 | + if (_rpmmi_debug || (dbi)->dbi_debug) |
1d20bd4e JR |
56 | + fprintf(stderr, "==> success orig requested (%d), configured buffer (%d), buffer (%d), size after dbiGet (%d)\n", |
57 | + origlen, vp->ulen, uhlen, vp->size); | |
58 | + else | |
076ab4d5 | 59 | + fprintf(stderr, "==> success\n"); |
1d20bd4e JR |
60 | } |
61 | } | |
62 | } else | |
63 | Index: rpm-5.4.9/rpmdb/db3.c | |
64 | =================================================================== | |
65 | --- rpm-5.4.9.orig/rpmdb/db3.c | |
66 | +++ rpm-5.4.9/rpmdb/db3.c | |
1c15eec5 JR |
67 | @@ -1442,6 +1442,8 @@ |
68 | rc = dbcursor->pget(dbcursor, key, pkey, data, flags); | |
69 | /* XXX DB_NOTFOUND can be returned */ | |
70 | _printit = (rc == DB_NOTFOUND ? 0 : _debug); | |
3346e176 JR |
71 | +// /* XXX Permit DB_BUFFER_SMALL to be returned (more restrictive?) */ |
72 | +// _printit = (rc == DB_BUFFER_SMALL ? 0 : _printit); | |
1c15eec5 JR |
73 | rc = cvtdberr(dbi, "dbcursor->pget", rc, _printit); |
74 | #else | |
75 | /* XXX db3 does DB_FIRST on uninitialized cursor */ | |
1d20bd4e JR |
76 | @@ -1452,7 +1452,7 @@ assert(db != NULL); |
77 | #endif | |
78 | } | |
79 | ||
80 | -DBIDEBUG(dbi, (stderr, "<-- %s(%p,%p,%p,%p,%p,0x%x) rc %d %s%s\n", __FUNCTION__, dbi, dbcursor, key, pkey, data, flags, rc, _DBCFLAGS(flags), _KEYDATA(key, pkey, data, NULL))); | |
81 | +DBIDEBUG(dbi, (stderr, "<-- %s(%p,%p,%p,%p,%p,0x%x) rc %d %s%s\n", __FUNCTION__, dbi, dbcursor, key, pkey, data, flags, rc, _DBCFLAGS(flags), _KEYDATA(key, pkey, rc == DB_BUFFER_SMALL ? NULL : data, NULL))); | |
82 | return rc; | |
83 | } | |
84 | /*@=mustmod@*/ |