Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 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 |
| 10 | end up trying 10 times. The new size is either the updated vp->size |
| 11 | from the failed pget call, or the previous size + 1024. |
| 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 | Upstream-Status: Inappropriate (workaround) |
| 18 | |
| 19 | Signed-off-by: Mark Hatle <mark.hatle@windriver.com> |
| 20 | |
| 21 | Index: rpm-5.4.14/rpmdb/rpmdb.c |
| 22 | =================================================================== |
| 23 | --- rpm-5.4.14.orig/rpmdb/rpmdb.c |
| 24 | +++ rpm-5.4.14/rpmdb/rpmdb.c |
| 25 | @@ -2212,8 +2212,12 @@ static int rpmmiGet(dbiIndex dbi, DBC * |
| 26 | vp->flags |= DB_DBT_USERMEM; |
| 27 | rc = dbiGet(dbi, dbcursor, kp, vp, flags); |
| 28 | if (rc == DB_BUFFER_SMALL) { |
| 29 | + int retry = 0; |
| 30 | + size_t origlen = vp->size; |
| 31 | size_t uhlen = vp->size; |
| 32 | - void * uh = mmap(NULL, uhlen, _prot, _flags, _fdno, _off); |
| 33 | + void * uh; |
| 34 | +retry_get: |
| 35 | + uh = mmap(NULL, uhlen, _prot, _flags, _fdno, _off); |
| 36 | if (uh == NULL || uh == (void *)-1) |
| 37 | fprintf(stderr, |
| 38 | "==> mmap(%p[%u], 0x%x, 0x%x, %d, 0x%x) error(%d): %s\n", |
| 39 | @@ -2235,6 +2239,25 @@ static int rpmmiGet(dbiIndex dbi, DBC * |
| 40 | if (munmap(uh, uhlen) != 0) |
| 41 | fprintf(stderr, "==> munmap(%p[%u]) error(%d): %s\n", |
| 42 | uh, (unsigned)uhlen, errno, strerror(errno)); |
| 43 | + /* We want to be sure to limit the number of retry attempts to avoid a loop! */ |
| 44 | + if (rc == DB_BUFFER_SMALL && retry < 10) { |
| 45 | + /* If we got a largr vp-size back, use that, otherwise increment the size by 1k */ |
| 46 | + uhlen = vp->size > uhlen ? vp->size : uhlen + 1024; |
| 47 | + retry++; |
| 48 | + if ((dbi)->dbi_debug) |
| 49 | + fprintf(stderr, "==> DB_BUFFER_SMALL orig requested (%d), configured (%d), forcing larger buffer (%d), new size (%d)\n", |
| 50 | + origlen, vp->ulen, uhlen, vp->size); |
| 51 | + else |
| 52 | + fprintf(stderr, "==> retry (%d) db3cpget (%d)\n", retry, uhlen); |
| 53 | + goto retry_get; |
| 54 | + } |
| 55 | + } |
| 56 | + if (retry) { |
| 57 | + if ((dbi)->dbi_debug) |
| 58 | + fprintf(stderr, "==> success orig requested (%d), configured buffer (%d), buffer (%d), size after dbiGet (%d)\n", |
| 59 | + origlen, vp->ulen, uhlen, vp->size); |
| 60 | + else |
| 61 | + fprintf(stderr, "==> success\n"); |
| 62 | } |
| 63 | } |
| 64 | } else |
| 65 | Index: rpm-5.4.14/rpmdb/db3.c |
| 66 | =================================================================== |
| 67 | --- rpm-5.4.14.orig/rpmdb/db3.c |
| 68 | +++ rpm-5.4.14/rpmdb/db3.c |
| 69 | @@ -1509,7 +1509,7 @@ assert(db != NULL); |
| 70 | #endif |
| 71 | } |
| 72 | |
| 73 | -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))); |
| 74 | +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))); |
| 75 | return rc; |
| 76 | } |
| 77 | /*@=mustmod@*/ |