1 In certain cases with BerkleyDB 5.3.x we are getting the error:
3 db3.c:1443: dbcursor->pget(-30999): BDB0063 DB_BUFFER_SMALL: User memory too small for return value
5 See https://bugs.launchpad.net/rpm/+bug/934420 for more information.
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 25 times. The new size is either the updated vp->size
11 from the failed pget call, or the previous size + 4096.
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
17 Signed-off-by: Mark Hatle <mark.hatle@windriver.com>
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) {
28 + size_t origlen = vp->size;
29 size_t uhlen = vp->size;
30 - void * uh = mmap(NULL, uhlen, _prot, _flags, _fdno, _off);
33 + uh = mmap(NULL, uhlen, _prot, _flags, _fdno, _off);
34 if (uh == NULL || uh == (void *)-1)
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! */
42 + if (rc == DB_BUFFER_SMALL && retry < 25) {
43 + /* If we got a largr vp-size back, use that, otherwise increment the size by 1k */
44 + uhlen = vp->size > uhlen ? vp->size : uhlen + 4096;
46 + if (_rpmmi_debug || (dbi)->dbi_debug)
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);
50 + fprintf(stderr, "==> retry (%d) db3cpget (%d)\n", retry, uhlen);
55 + if (_rpmmi_debug || (dbi)->dbi_debug)
56 + fprintf(stderr, "==> success orig requested (%d), configured buffer (%d), buffer (%d), size after dbiGet (%d)\n",
57 + origlen, vp->ulen, uhlen, vp->size);
59 + fprintf(stderr, "==> success\n");
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
68 rc = dbcursor->pget(dbcursor, key, pkey, data, flags);
69 /* XXX DB_NOTFOUND can be returned */
70 _printit = (rc == DB_NOTFOUND ? 0 : _debug);
71 +// /* XXX Permit DB_BUFFER_SMALL to be returned (more restrictive?) */
72 +// _printit = (rc == DB_BUFFER_SMALL ? 0 : _printit);
73 rc = cvtdberr(dbi, "dbcursor->pget", rc, _printit);
75 /* XXX db3 does DB_FIRST on uninitialized cursor */
76 @@ -1452,7 +1452,7 @@ assert(db != NULL);
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)));