diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 00e63adc933f134c55d680cf347650cf950aa798..783d3a822e50b60febfae941274e1eb162cd852b 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -3975,6 +3975,8 @@ BOOL LLAppearanceMgr::getIsInCOF(const LLUUID& obj_id) const
 	return FALSE;
 }
 
+// FIXME apparent duplicate of isLinkedInCOF()
+
 // static
 bool LLAppearanceMgr::isLinkInCOF(const LLUUID& obj_id)
 {
diff --git a/indra/newview/llattachmentsmgr.cpp b/indra/newview/llattachmentsmgr.cpp
index a38bae207db44716e51177ceaa52cdf2ca6e6719..e64ed6563a1be9e55ce768ad9203d426b3d385ca 100755
--- a/indra/newview/llattachmentsmgr.cpp
+++ b/indra/newview/llattachmentsmgr.cpp
@@ -117,6 +117,7 @@ void LLAttachmentsMgr::linkPendingAttachments()
 	{
 		LLPointer<LLInventoryCallback> cb = new LLAttachAfterLinkCallback(mPendingAttachments);
 		LLInventoryObject::const_object_list_t inv_items_to_link;
+		LL_DEBUGS("Avatar") << "ATT requesting COF links for " << mPendingAttachments.size() << " object(s):" << LL_ENDL;
 		for (attachments_vec_t::const_iterator it = mPendingAttachments.begin();
 			 it != mPendingAttachments.end(); ++it)
 		{
@@ -124,6 +125,7 @@ void LLAttachmentsMgr::linkPendingAttachments()
 			LLViewerInventoryItem *item = gInventory.getItem(att_info.mItemID);
 			if (item)
 			{
+				LL_DEBUGS("Avatar") << "ATT - requesting COF link for " << item->getName() << LL_ENDL;
 				inv_items_to_link.push_back(item);
 			}
 			else
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index e8d5db44377e733207e346a63d07e989bc30ed98..8dde2c33b7c6d463910f67bcc33bbe6b4ec43cee 100755
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -687,4 +687,10 @@ void hide_context_entries(LLMenuGL& menu,
 						  const menuentry_vec_t &entries_to_show, 
 						  const menuentry_vec_t &disabled_entries);
 
+// Helper functions to classify actions.
+bool isAddAction(const std::string& action);
+bool isRemoveAction(const std::string& action);
+bool isMarketplaceCopyAction(const std::string& action);
+bool isMarketplaceSendAction(const std::string& action);
+
 #endif // LL_LLINVENTORYBRIDGE_H
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 1abc09bf3b7fc49b7e6b496671048a13ac083034..6096cad3a5a9c361e840d5fa628eac16ebee5443 100755
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -1060,6 +1060,34 @@ void LLOpenFoldersWithSelection::doFolder(LLFolderViewFolder* folder)
 	}
 }
 
+// Succeeds iff all selected items are bridges to objects, in which
+// case returns their corresponding uuids.
+bool get_selection_object_uuids(LLFolderView *root, uuid_vec_t& ids)
+{
+	uuid_vec_t results;
+	S32 non_object = 0;
+	LLFolderView::selected_items_t selectedItems = root->getSelectedItems();
+	for(LLFolderView::selected_items_t::iterator it = selectedItems.begin(); it != selectedItems.end(); ++it)
+	{
+		LLObjectBridge *view_model = dynamic_cast<LLObjectBridge *>((*it)->getViewModelItem());
+
+		if(view_model && view_model->getUUID().notNull())
+		{
+			results.push_back(view_model->getUUID());
+		}
+		else
+		{
+			non_object++;
+		}
+	}
+	if (non_object == 0)
+	{
+		ids = results;
+		return true;
+	}
+	return false;
+}
+
 void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root, const std::string& action)
 {
 	if ("rename" == action)
@@ -1116,13 +1144,29 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
 
 	std::set<LLFolderViewItem*>::iterator set_iter;
 
-	for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter)
+
+	// This rather warty piece of code is to allow items to be removed
+	// from the avatar in a batch, eliminating redundant
+	// updateAppearanceFromCOF() requests further down the line. (MAINT-4918)
+	//
+	// There are probably other cases where similar batching would be
+	// desirable, but the current item-by-item performAction()
+	// approach would need to be reworked.
+	uuid_vec_t object_uuids_to_remove;
+	if (isRemoveAction(action) && get_selection_object_uuids(root, object_uuids_to_remove))
 	{
-		LLFolderViewItem* folder_item = *set_iter;
-		if(!folder_item) continue;
-		LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem();
-		if(!bridge) continue;
-		bridge->performAction(model, action);
+		LLAppearanceMgr::instance().removeItemsFromAvatar(object_uuids_to_remove);
+	}
+	else
+	{
+		for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter)
+		{
+			LLFolderViewItem* folder_item = *set_iter;
+			if(!folder_item) continue;
+			LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem();
+			if(!bridge) continue;
+			bridge->performAction(model, action);
+		}
 	}
 
 	LLFloater::setFloaterHost(NULL);