 doc/src/sgml/catalogs.sgml         |    4 +-
 src/backend/commands/seclabel.c    |   41 +++++++++++++++++++++++++++++++----
 src/backend/utils/cache/syscache.c |   12 ++++++++++
 src/include/catalog/indexing.h     |    2 +-
 src/include/catalog/pg_seclabel.h  |    2 +-
 src/include/utils/syscache.h       |    1 +
 6 files changed, 53 insertions(+), 9 deletions(-)

diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 713ee25..6c57f7d 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -4722,7 +4722,7 @@
 
      <row>
       <entry><structfield>provider</structfield></entry>
-      <entry><type>text</type></entry>
+      <entry><type>name</type></entry>
       <entry></entry>
       <entry>The label provider associated with this label.</entry>
      </row>
@@ -7564,7 +7564,7 @@
      </row>
      <row>
       <entry><structfield>provider</structfield></entry>
-      <entry><type>text</type></entry>
+      <entry><type>name</type></entry>
       <entry><literal><link linkend="catalog-pg-seclabel"><structname>pg_seclabel</structname></link>.provider</literal></entry>
       <entry>The label provider associated with this label.</entry>
      </row>
diff --git a/src/backend/commands/seclabel.c b/src/backend/commands/seclabel.c
index 51a5567..012fc28 100644
--- a/src/backend/commands/seclabel.c
+++ b/src/backend/commands/seclabel.c
@@ -15,12 +15,14 @@
 #include "catalog/catalog.h"
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
+#include "catalog/pg_largeobject.h"
 #include "catalog/pg_seclabel.h"
 #include "commands/seclabel.h"
 #include "miscadmin.h"
 #include "utils/acl.h"
 #include "utils/builtins.h"
 #include "utils/fmgroids.h"
+#include "utils/syscache.h"
 #include "utils/lsyscache.h"
 #include "utils/memutils.h"
 #include "utils/tqual.h"
@@ -150,6 +152,33 @@ GetSecurityLabel(const ObjectAddress *object, const char *provider)
 
 	Assert(!IsSharedRelation(object->classId));
 
+	/*
+	 * XXX - The reason why we don't reference security label of
+	 * large objects is the number of large objects being scanned
+	 * is unexpectable. If we would try to scan millions of objects,
+	 * the syscache mechanism must have a complex cache reclaim
+	 * mechanism. However, frequent cache flushing is fundamentally
+	 * nonsense. So, we always use raw scanning for large objects.
+	 */
+	if (object->classId != LargeObjectRelationId)
+	{
+		tuple = SearchSysCache4(SECLABELOID,
+								ObjectIdGetDatum(object->objectId),
+								ObjectIdGetDatum(object->classId),
+								Int32GetDatum(object->objectSubId),
+								CStringGetDatum(provider));
+		if (HeapTupleIsValid(tuple))
+		{
+			datum = SysCacheGetAttr(SECLABELOID, tuple,
+									Anum_pg_seclabel_label, &isnull);
+			if (!isnull)
+				seclabel = TextDatumGetCString(datum);
+
+			ReleaseSysCache(tuple);
+		}
+		return seclabel;
+	}
+
 	ScanKeyInit(&keys[0],
 				Anum_pg_seclabel_objoid,
 				BTEqualStrategyNumber, F_OIDEQ,
@@ -164,8 +193,8 @@ GetSecurityLabel(const ObjectAddress *object, const char *provider)
 				Int32GetDatum(object->objectSubId));
 	ScanKeyInit(&keys[3],
 				Anum_pg_seclabel_provider,
-				BTEqualStrategyNumber, F_TEXTEQ,
-				CStringGetTextDatum(provider));
+				BTEqualStrategyNumber, F_NAMEEQ,
+				CStringGetDatum(provider));
 
 	pg_seclabel = heap_open(SecLabelRelationId, AccessShareLock);
 
@@ -201,6 +230,7 @@ SetSecurityLabel(const ObjectAddress *object,
 	SysScanDesc scan;
 	HeapTuple	oldtup;
 	HeapTuple	newtup = NULL;
+	NameData	name;
 	Datum		values[Natts_pg_seclabel];
 	bool		nulls[Natts_pg_seclabel];
 	bool		replaces[Natts_pg_seclabel];
@@ -211,10 +241,11 @@ SetSecurityLabel(const ObjectAddress *object,
 	/* Prepare to form or update a tuple, if necessary. */
 	memset(nulls, false, sizeof(nulls));
 	memset(replaces, false, sizeof(replaces));
+	namestrcpy(&name, provider);
 	values[Anum_pg_seclabel_objoid - 1] = ObjectIdGetDatum(object->objectId);
 	values[Anum_pg_seclabel_classoid - 1] = ObjectIdGetDatum(object->classId);
 	values[Anum_pg_seclabel_objsubid - 1] = Int32GetDatum(object->objectSubId);
-	values[Anum_pg_seclabel_provider - 1] = CStringGetTextDatum(provider);
+	values[Anum_pg_seclabel_provider - 1] = NameGetDatum(&name);
 	if (label != NULL)
 		values[Anum_pg_seclabel_label - 1] = CStringGetTextDatum(label);
 
@@ -233,8 +264,8 @@ SetSecurityLabel(const ObjectAddress *object,
 				Int32GetDatum(object->objectSubId));
 	ScanKeyInit(&keys[3],
 				Anum_pg_seclabel_provider,
-				BTEqualStrategyNumber, F_TEXTEQ,
-				CStringGetTextDatum(provider));
+				BTEqualStrategyNumber, F_NAMEEQ,
+				CStringGetDatum(provider));
 
 	pg_seclabel = heap_open(SecLabelRelationId, RowExclusiveLock);
 
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index 99e5f1d..18194d1 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -44,6 +44,7 @@
 #include "catalog/pg_opfamily.h"
 #include "catalog/pg_proc.h"
 #include "catalog/pg_rewrite.h"
+#include "catalog/pg_seclabel.h"
 #include "catalog/pg_statistic.h"
 #include "catalog/pg_tablespace.h"
 #include "catalog/pg_ts_config.h"
@@ -587,6 +588,17 @@ static const struct cachedesc cacheinfo[] = {
 		},
 		1024
 	},
+	{SecLabelRelationId,        /* SECLABELOID */
+		SecLabelObjectIndexId,
+		4,
+		{
+			Anum_pg_seclabel_objoid,
+			Anum_pg_seclabel_classoid,
+			Anum_pg_seclabel_objsubid,
+			Anum_pg_seclabel_provider
+		},
+		2048
+	},
 	{StatisticRelationId,		/* STATRELATTINH */
 		StatisticRelidAttnumInhIndexId,
 		3,
diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h
index 4118e64..6b5a7aa 100644
--- a/src/include/catalog/indexing.h
+++ b/src/include/catalog/indexing.h
@@ -291,7 +291,7 @@ DECLARE_UNIQUE_INDEX(pg_default_acl_oid_index, 828, on pg_default_acl using btre
 DECLARE_UNIQUE_INDEX(pg_db_role_setting_databaseid_rol_index, 2965, on pg_db_role_setting using btree(setdatabase oid_ops, setrole oid_ops));
 #define DbRoleSettingDatidRolidIndexId	2965
 
-DECLARE_UNIQUE_INDEX(pg_seclabel_object_index, 3597, on pg_seclabel using btree(objoid oid_ops, classoid oid_ops, objsubid int4_ops, provider text_ops));
+DECLARE_UNIQUE_INDEX(pg_seclabel_object_index, 3597, on pg_seclabel using btree(objoid oid_ops, classoid oid_ops, objsubid int4_ops, provider name_ops));
 #define SecLabelObjectIndexId				3597
 
 DECLARE_UNIQUE_INDEX(pg_extension_oid_index, 3080, on pg_extension using btree(oid oid_ops));
diff --git a/src/include/catalog/pg_seclabel.h b/src/include/catalog/pg_seclabel.h
index 1f9a6a0..1ed8b87 100644
--- a/src/include/catalog/pg_seclabel.h
+++ b/src/include/catalog/pg_seclabel.h
@@ -25,7 +25,7 @@ CATALOG(pg_seclabel,3596) BKI_WITHOUT_OIDS
 	Oid			objoid;			/* OID of the object itself */
 	Oid			classoid;		/* OID of table containing the object */
 	int4		objsubid;		/* column number, or 0 if not used */
-	text		provider;		/* name of label provider */
+	NameData	provider;		/* name of label provider */
 	text		label;			/* security label of the object */
 } FormData_pg_seclabel;
 
diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h
index 55d2230..4fbbab5 100644
--- a/src/include/utils/syscache.h
+++ b/src/include/utils/syscache.h
@@ -73,6 +73,7 @@ enum SysCacheIdentifier
 	RELNAMENSP,
 	RELOID,
 	RULERELNAME,
+	SECLABELOID,
 	STATRELATTINH,
 	TABLESPACEOID,
 	TSCONFIGMAP,