2a5b6a
diff --git a/rpmio/rpmio.c b/rpmio/rpmio.c
2a5b6a
index cd223e8..f23fc11 100644
2a5b6a
--- a/rpmio/rpmio.c
2a5b6a
+++ b/rpmio/rpmio.c
2a5b6a
@@ -5,6 +5,7 @@
2a5b6a
 #include "system.h"
2a5b6a
 #include <stdarg.h>
2a5b6a
 #include <errno.h>
2a5b6a
+#include <ctype.h>
2a5b6a
 
2a5b6a
 #include <rpm/rpmlog.h>
2a5b6a
 #include <rpm/rpmmacro.h>
2a5b6a
@@ -873,7 +874,12 @@ static const char * getFdErrstr (FD_t fd)
2a5b6a
 
2a5b6a
 #include <sys/types.h>
2a5b6a
 #include <inttypes.h>
2a5b6a
+#define LZMA_UNSTABLE
2a5b6a
 #include <lzma.h>
2a5b6a
+/* Multithreading support in stable API since xz 5.2.0 */
2a5b6a
+#if LZMA_VERSION >= 50010020
2a5b6a
+#define HAVE_LZMA_MT
2a5b6a
+#endif
2a5b6a
 
2a5b6a
 #define kBufferSize (1 << 15)
2a5b6a
 
2a5b6a
@@ -897,7 +902,10 @@ static LZFILE *lzopen_internal(const char *path, const char *mode, int fd, int x
2a5b6a
     LZFILE *lzfile;
2a5b6a
     lzma_ret ret;
2a5b6a
     lzma_stream init_strm = LZMA_STREAM_INIT;
2a5b6a
-
2a5b6a
+    uint64_t mem_limit = rpmExpandNumeric("%{_xz_memlimit}");
2a5b6a
+#ifdef HAVE_LZMA_MT
2a5b6a
+    int threads = 0;
2a5b6a
+#endif
2a5b6a
     for (; *mode; mode++) {
2a5b6a
 	if (*mode == 'w')
2a5b6a
 	    encoding = 1;
2a5b6a
@@ -905,6 +913,21 @@ static LZFILE *lzopen_internal(const char *path, const char *mode, int fd, int x
2a5b6a
 	    encoding = 0;
2a5b6a
 	else if (*mode >= '1' && *mode <= '9')
2a5b6a
 	    level = *mode - '0';
2a5b6a
+	else if (*mode == 'T') {
2a5b6a
+	    if (isdigit(*(mode+1))) {
2a5b6a
+#ifdef HAVE_LZMA_MT
2a5b6a
+		threads = atoi(++mode);
2a5b6a
+#endif
2a5b6a
+		/* skip past rest of digits in string that atoi()
2a5b6a
+		 * should've processed
2a5b6a
+		 * */
2a5b6a
+		while(isdigit(*++mode));
2a5b6a
+	    }
2a5b6a
+#ifdef HAVE_LZMA_MT
2a5b6a
+	    else
2a5b6a
+		threads = -1;
2a5b6a
+#endif
2a5b6a
+	}
2a5b6a
     }
2a5b6a
     if (fd != -1)
2a5b6a
 	fp = fdopen(fd, encoding ? "w" : "r");
2a5b6a
@@ -924,16 +947,48 @@ static LZFILE *lzopen_internal(const char *path, const char *mode, int fd, int x
2a5b6a
     lzfile->strm = init_strm;
2a5b6a
     if (encoding) {
2a5b6a
 	if (xz) {
2a5b6a
-	    ret = lzma_easy_encoder(&lzfile->strm, level, LZMA_CHECK_SHA256);
2a5b6a
+#ifdef HAVE_LZMA_MT
2a5b6a
+	    if (!threads) {
2a5b6a
+#endif
2a5b6a
+		ret = lzma_easy_encoder(&lzfile->strm, level, LZMA_CHECK_SHA256);
2a5b6a
+#ifdef HAVE_LZMA_MT
2a5b6a
+	    } else {
2a5b6a
+		if (threads == -1)
2a5b6a
+		    threads = sysconf(_SC_NPROCESSORS_ONLN);
2a5b6a
+		lzma_mt mt_options = {
2a5b6a
+		    .flags = 0,
2a5b6a
+		    .threads = threads,
2a5b6a
+		    .block_size = 0,
2a5b6a
+		    .timeout = 0,
2a5b6a
+		    .preset = level,
2a5b6a
+		    .filters = NULL,
2a5b6a
+		    .check = LZMA_CHECK_SHA256 };
2a5b6a
+
2a5b6a
+		ret = lzma_stream_encoder_mt(&lzfile->strm, &mt_options);
2a5b6a
+	    }
2a5b6a
+#endif
2a5b6a
 	} else {
2a5b6a
 	    lzma_options_lzma options;
2a5b6a
 	    lzma_lzma_preset(&options, level);
2a5b6a
 	    ret = lzma_alone_encoder(&lzfile->strm, &options);
2a5b6a
 	}
2a5b6a
-    } else {	/* lzma_easy_decoder_memusage(level) is not ready yet, use hardcoded limit for now */
2a5b6a
-	ret = lzma_auto_decoder(&lzfile->strm, 100<<20, 0);
2a5b6a
+    } else {   /* lzma_easy_decoder_memusage(level) is not ready yet, use hardcoded limit for now */
2a5b6a
+	ret = lzma_auto_decoder(&lzfile->strm, mem_limit ? mem_limit : 100<<20, 0);
2a5b6a
     }
2a5b6a
     if (ret != LZMA_OK) {
2a5b6a
+	switch (ret) {
2a5b6a
+	    case LZMA_MEM_ERROR:
2a5b6a
+		rpmlog(RPMLOG_ERR, "liblzma: Memory allocation failed");
2a5b6a
+		break;
2a5b6a
+
2a5b6a
+	    case LZMA_DATA_ERROR:
2a5b6a
+		rpmlog(RPMLOG_ERR, "liblzma: File size limits exceeded");
2a5b6a
+		break;
2a5b6a
+
2a5b6a
+	    default:
2a5b6a
+		rpmlog(RPMLOG_ERR, "liblzma: 
2a5b6a
+		break;
2a5b6a
+	}
2a5b6a
 	fclose(fp);
2a5b6a
 	free(lzfile);
2a5b6a
 	return 0;