diff --git a/include/grpc/impl/codegen/slice.h b/include/grpc/impl/codegen/slice.h
index c684b7587d634f2078a03ce5cf55ec5dbe2aa460..dfc0a774fcc12db6382811b2aa89a20104663401 100644
--- a/include/grpc/impl/codegen/slice.h
+++ b/include/grpc/impl/codegen/slice.h
@@ -120,6 +120,14 @@ GPRAPI void gpr_slice_unref(gpr_slice s);
    passed in at destruction. */
 GPRAPI gpr_slice gpr_slice_new(void *p, size_t len, void (*destroy)(void *));
 
+/* Equivalent to gpr_slice_new, but with a separate pointer that is
+   passed to the destroy function.  This function can be useful when
+   the data is part of a larger structure that must be destroyed when
+   the data is no longer needed. */
+GPRAPI gpr_slice gpr_slice_new_with_user_data(void *p, size_t len,
+                                              void (*destroy)(void *),
+                                              void *user_data);
+
 /* Equivalent to gpr_slice_new, but with a two argument destroy function that
    also takes the slice length. */
 GPRAPI gpr_slice gpr_slice_new_with_len(void *p, size_t len,
diff --git a/src/core/lib/support/slice.c b/src/core/lib/support/slice.c
index b9a7c77bda6e649eca6635e0dcd84b19462dd95b..8a2c0a908657e4d69dd361aed2a807fc9e1996db 100644
--- a/src/core/lib/support/slice.c
+++ b/src/core/lib/support/slice.c
@@ -94,14 +94,16 @@ static void new_slice_unref(void *p) {
   }
 }
 
-gpr_slice gpr_slice_new(void *p, size_t len, void (*destroy)(void *)) {
+gpr_slice gpr_slice_new_with_user_data(void *p, size_t len,
+                                       void (*destroy)(void *),
+                                       void *user_data) {
   gpr_slice slice;
   new_slice_refcount *rc = gpr_malloc(sizeof(new_slice_refcount));
   gpr_ref_init(&rc->refs, 1);
   rc->rc.ref = new_slice_ref;
   rc->rc.unref = new_slice_unref;
   rc->user_destroy = destroy;
-  rc->user_data = p;
+  rc->user_data = user_data;
 
   slice.refcount = &rc->rc;
   slice.data.refcounted.bytes = p;
@@ -109,6 +111,11 @@ gpr_slice gpr_slice_new(void *p, size_t len, void (*destroy)(void *)) {
   return slice;
 }
 
+gpr_slice gpr_slice_new(void *p, size_t len, void (*destroy)(void *)) {
+  /* Pass "p" to *destroy when the slice is no longer needed. */
+  return gpr_slice_new_with_user_data(p, len, destroy, p);
+}
+
 /* gpr_slice_new_with_len support structures - we create a refcount object
    extended with the user provided data pointer & destroy function */
 typedef struct new_with_len_slice_refcount {
diff --git a/test/core/support/slice_test.c b/test/core/support/slice_test.c
index 0da483a3216d14f8c3b77bf36f1840cba3ddfb16..06c364b368078e584a97fcdc16d66848e1d61f65 100644
--- a/test/core/support/slice_test.c
+++ b/test/core/support/slice_test.c
@@ -85,6 +85,27 @@ static void test_slice_new_returns_something_sensible(void) {
   gpr_slice_unref(slice);
 }
 
+/* destroy function that sets a mark to indicate it was called. */
+static void set_mark(void *p) { *((int *)p) = 1; }
+
+static void test_slice_new_with_user_data(void) {
+  int marker = 0;
+  uint8_t buf[2];
+  gpr_slice slice;
+
+  buf[0] = 0;
+  buf[1] = 1;
+  slice = gpr_slice_new_with_user_data(buf, 2, set_mark, &marker);
+  GPR_ASSERT(marker == 0);
+  GPR_ASSERT(GPR_SLICE_LENGTH(slice) == 2);
+  GPR_ASSERT(GPR_SLICE_START_PTR(slice)[0] == 0);
+  GPR_ASSERT(GPR_SLICE_START_PTR(slice)[1] == 1);
+
+  /* unref should cause destroy function to run. */
+  gpr_slice_unref(slice);
+  GPR_ASSERT(marker == 1);
+}
+
 static int do_nothing_with_len_1_calls = 0;
 
 static void do_nothing_with_len_1(void *ignored, size_t len) {
@@ -232,6 +253,7 @@ int main(int argc, char **argv) {
   grpc_test_init(argc, argv);
   test_slice_malloc_returns_something_sensible();
   test_slice_new_returns_something_sensible();
+  test_slice_new_with_user_data();
   test_slice_new_with_len_returns_something_sensible();
   for (length = 0; length < 128; length++) {
     test_slice_sub_works(length);