Blame SOURCES/db-5.3.21-memp_stat-upstream-fix.patch

b1d0b3
diff -r -u db-5.3.21_orig/src/mp/mp_stat.c db-5.3.21/src/mp/mp_stat.c
b1d0b3
--- db-5.3.21_orig/src/mp/mp_stat.c	2012-05-12 01:57:53.000000000 +0800
b1d0b3
+++ db-5.3.21/src/mp/mp_stat.c	2015-05-19 15:07:09.000000000 +0800
b1d0b3
@@ -87,6 +87,13 @@
b1d0b3
 	u_int32_t i;
b1d0b3
 	uintmax_t tmp_wait, tmp_nowait;
b1d0b3
 
b1d0b3
+	/*
b1d0b3
+	 * The array holding the lengths related to the buffer allocated for *fspp.
b1d0b3
+	 * The first element of the array holds the number of entries allocated.
b1d0b3
+	 * The second element of the array holds the total number of bytes allocated.
b1d0b3
+	 */
b1d0b3
+	u_int32_t fsp_len[2];
b1d0b3
+
b1d0b3
 	dbmp = env->mp_handle;
b1d0b3
 	mp = dbmp->reginfo[0].primary;
b1d0b3
 
b1d0b3
@@ -193,32 +200,53 @@
b1d0b3
 	if (fspp != NULL) {
b1d0b3
 		*fspp = NULL;
b1d0b3
 
b1d0b3
-		/* Count the MPOOLFILE structures. */
b1d0b3
-		i = 0;
b1d0b3
-		len = 0;
b1d0b3
-		if ((ret = __memp_walk_files(env,
b1d0b3
-		     mp, __memp_count_files, &len, &i, flags)) != 0)
b1d0b3
-			return (ret);
b1d0b3
+		while (*fspp == NULL) {
b1d0b3
+			/* Count the MPOOLFILE structures. */
b1d0b3
+			i = 0;
b1d0b3
+			/*
b1d0b3
+			 * Allow space for the first __memp_get_files() to align the
b1d0b3
+			 * structure array to uintmax_t, DB_MPOOL_STAT's most
b1d0b3
+			 * restrictive field.  [#23150]
b1d0b3
+			 */
b1d0b3
+			len = sizeof(uintmax_t);
b1d0b3
+			if ((ret = __memp_walk_files(env,
b1d0b3
+			     mp, __memp_count_files, &len, &i, flags)) != 0)
b1d0b3
+				return (ret);
b1d0b3
+
b1d0b3
+			if (i == 0)
b1d0b3
+				return (0);
b1d0b3
+
b1d0b3
+			/* 
b1d0b3
+			 * Copy the number of DB_MPOOL_FSTAT entries and the number of
b1d0b3
+			 * bytes allocated for them into fsp_len. Do not count the space
b1d0b3
+			 * reserved for allignment.
b1d0b3
+			 */
b1d0b3
+			fsp_len[0] = i;
b1d0b3
+			fsp_len[1] = len - sizeof(uintmax_t);
b1d0b3
 
b1d0b3
-		if (i == 0)
b1d0b3
-			return (0);
b1d0b3
-		len += sizeof(DB_MPOOL_FSTAT *);	/* Trailing NULL */
b1d0b3
+			len += sizeof(DB_MPOOL_FSTAT *);	/* Trailing NULL */
b1d0b3
 
b1d0b3
-		/* Allocate space */
b1d0b3
-		if ((ret = __os_umalloc(env, len, fspp)) != 0)
b1d0b3
-			return (ret);
b1d0b3
+			/* Allocate space */
b1d0b3
+			if ((ret = __os_umalloc(env, len, fspp)) != 0)
b1d0b3
+				return (ret);
b1d0b3
 
b1d0b3
-		tfsp = *fspp;
b1d0b3
-		*tfsp = NULL;
b1d0b3
-
b1d0b3
-		/*
b1d0b3
-		 * Files may have been opened since we counted, don't walk
b1d0b3
-		 * off the end of the allocated space.
b1d0b3
-		 */
b1d0b3
-		if ((ret = __memp_walk_files(env,
b1d0b3
-		    mp, __memp_get_files, &tfsp, &i, flags)) != 0)
b1d0b3
-			return (ret);
b1d0b3
+			tfsp = *fspp;
b1d0b3
+			*tfsp = NULL;
b1d0b3
 
b1d0b3
+			/*
b1d0b3
+			 * Files may have been opened since we counted, if we walk off
b1d0b3
+			 * the end of the allocated space specified in fsp_len, retry.
b1d0b3
+			 */
b1d0b3
+			if ((ret = __memp_walk_files(env,
b1d0b3
+			    mp, __memp_get_files, &tfsp, fsp_len, flags)) != 0) {
b1d0b3
+				if (ret == DB_BUFFER_SMALL) {
b1d0b3
+					__os_ufree(env, *fspp);
b1d0b3
+					*fspp = NULL;
b1d0b3
+					tfsp = NULL;
b1d0b3
+				} else
b1d0b3
+					return (ret);
b1d0b3
+			}
b1d0b3
+		}
b1d0b3
 		*++tfsp = NULL;
b1d0b3
 	}
b1d0b3
 
b1d0b3
@@ -286,28 +314,35 @@
b1d0b3
  * for the text file names.
b1d0b3
  */
b1d0b3
 static int
b1d0b3
-__memp_get_files(env, mfp, argp, countp, flags)
b1d0b3
+__memp_get_files(env, mfp, argp, fsp_len, flags)
b1d0b3
 	ENV *env;
b1d0b3
 	MPOOLFILE *mfp;
b1d0b3
 	void *argp;
b1d0b3
-	u_int32_t *countp;
b1d0b3
+	u_int32_t fsp_len[];
b1d0b3
 	u_int32_t flags;
b1d0b3
 {
b1d0b3
 	DB_MPOOL *dbmp;
b1d0b3
 	DB_MPOOL_FSTAT **tfsp, *tstruct;
b1d0b3
 	char *name, *tname;
b1d0b3
-	size_t nlen;
b1d0b3
+	size_t nlen, tlen;
b1d0b3
 
b1d0b3
-	if (*countp == 0)
b1d0b3
-		return (0);
b1d0b3
+	/* We walked through more files than argp was allocated for. */
b1d0b3
+	if (fsp_len[0] == 0)
b1d0b3
+		return DB_BUFFER_SMALL;
b1d0b3
 
b1d0b3
 	dbmp = env->mp_handle;
b1d0b3
 	tfsp = *(DB_MPOOL_FSTAT ***)argp;
b1d0b3
 
b1d0b3
 	if (*tfsp == NULL) {
b1d0b3
-		/* Add 1 to count because we need to skip over the NULL. */
b1d0b3
-		tstruct = (DB_MPOOL_FSTAT *)(tfsp + *countp + 1);
b1d0b3
-		tname = (char *)(tstruct + *countp);
b1d0b3
+		/*
b1d0b3
+		 * Add 1 to count because to skip over the NULL end marker.
b1d0b3
+		 * Align it further for DB_MPOOL_STAT's most restrictive field
b1d0b3
+		 * because uintmax_t might require stricter alignment than
b1d0b3
+		 * pointers; e.g., IP32 LL64 SPARC. [#23150]
b1d0b3
+		 */
b1d0b3
+		tstruct = (DB_MPOOL_FSTAT *)&tfsp[fsp_len[0] + 1];
b1d0b3
+		tstruct = ALIGNP_INC(tstruct, sizeof(uintmax_t));
b1d0b3
+		tname = (char *)&tstruct[fsp_len[0]];
b1d0b3
 		*tfsp = tstruct;
b1d0b3
 	} else {
b1d0b3
 		tstruct = *tfsp + 1;
b1d0b3
@@ -317,6 +352,15 @@
b1d0b3
 
b1d0b3
 	name = __memp_fns(dbmp, mfp);
b1d0b3
 	nlen = strlen(name) + 1;
b1d0b3
+
b1d0b3
+	/* The space required for file names is larger than argp was allocated for. */
b1d0b3
+	tlen = sizeof(DB_MPOOL_FSTAT *) + sizeof(DB_MPOOL_FSTAT) + nlen;
b1d0b3
+	if (fsp_len[1] < tlen)
b1d0b3
+		return DB_BUFFER_SMALL;
b1d0b3
+	else
b1d0b3
+		/* Count down the number of bytes left in argp. */
b1d0b3
+		fsp_len[1] -= tlen;
b1d0b3
+
b1d0b3
 	memcpy(tname, name, nlen);
b1d0b3
 	memcpy(tstruct, &mfp->stat, sizeof(mfp->stat));
b1d0b3
 	tstruct->file_name = tname;
b1d0b3
@@ -325,7 +369,9 @@
b1d0b3
 	tstruct->st_pagesize = mfp->pagesize;
b1d0b3
 
b1d0b3
 	*(DB_MPOOL_FSTAT ***)argp = tfsp;
b1d0b3
-	(*countp)--;
b1d0b3
+
b1d0b3
+	/* Count down the number of entries left in argp. */
b1d0b3
+	fsp_len[0]--;
b1d0b3
 
b1d0b3
 	if (LF_ISSET(DB_STAT_CLEAR))
b1d0b3
 		memset(&mfp->stat, 0, sizeof(mfp->stat));
b1d0b3
diff -r -u db-5.3.21_orig/src/mp/mp_sync.c db-5.3.21/src/mp/mp_sync.c
b1d0b3
--- db-5.3.21_orig/src/mp/mp_sync.c	2012-05-12 01:57:53.000000000 +0800
b1d0b3
+++ db-5.3.21/src/mp/mp_sync.c	2015-05-19 15:08:05.000000000 +0800
b1d0b3
@@ -57,11 +57,13 @@
b1d0b3
 			if ((t_ret = func(env,
b1d0b3
 			    mfp, arg, countp, flags)) != 0 && ret == 0)
b1d0b3
 				ret = t_ret;
b1d0b3
-			if (ret != 0 && !LF_ISSET(DB_STAT_MEMP_NOERROR))
b1d0b3
+			if (ret != 0 &&
b1d0b3
+			    (!LF_ISSET(DB_STAT_MEMP_NOERROR) || ret == DB_BUFFER_SMALL))
b1d0b3
 				break;
b1d0b3
 		}
b1d0b3
 		MUTEX_UNLOCK(env, hp->mtx_hash);
b1d0b3
-		if (ret != 0 && !LF_ISSET(DB_STAT_MEMP_NOERROR))
b1d0b3
+		if (ret != 0 &&
b1d0b3
+		    (!LF_ISSET(DB_STAT_MEMP_NOERROR) || ret == DB_BUFFER_SMALL))
b1d0b3
 			break;
b1d0b3
 	}
b1d0b3
 	return (ret);