diff --git a/NEWS b/NEWS
index b6a64d4c3..145361c35 100644
--- a/NEWS
+++ b/NEWS
@@ -36,6 +36,8 @@ ver 0.20 (not yet released)
 * support libsystemd (instead of the older libsystemd-daemon)
 * database
   - proxy: add TCP keepalive option
+* update
+  - apply .mpdignore matches to subdirectories
 
 ver 0.19.10 (2015/06/21)
 * input
diff --git a/doc/user.xml b/doc/user.xml
index a08a5aec0..8a37a7cce 100644
--- a/doc/user.xml
+++ b/doc/user.xml
@@ -1077,6 +1077,8 @@ database {
         To exclude a file from the update, create a file called
         <filename>.mpdignore</filename> in its parent directory.  Each
         line of that file may contain a list of shell wildcards.
+        Matching files in the current directory and all subdirectories
+        are excluded.
       </para>
     </section>
 
diff --git a/src/db/update/ExcludeList.cxx b/src/db/update/ExcludeList.cxx
index 3b54d635e..b09f349ac 100644
--- a/src/db/update/ExcludeList.cxx
+++ b/src/db/update/ExcludeList.cxx
@@ -89,6 +89,12 @@ ExcludeList::Check(Path name_fs) const
 	/* XXX include full path name in check */
 
 #ifdef HAVE_CLASS_GLOB
+	if (parent != nullptr) {
+		if (parent->Check(name_fs)) {
+			return true;
+		}
+	}
+
 	for (const auto &i : patterns)
 		if (i.Check(NarrowPath(name_fs).c_str()))
 			return true;
diff --git a/src/db/update/ExcludeList.hxx b/src/db/update/ExcludeList.hxx
index de48bac99..4952d291a 100644
--- a/src/db/update/ExcludeList.hxx
+++ b/src/db/update/ExcludeList.hxx
@@ -36,15 +36,23 @@
 class Path;
 
 class ExcludeList {
+	const ExcludeList *const parent;
+
 #ifdef HAVE_CLASS_GLOB
 	std::forward_list<Glob> patterns;
 #endif
 
 public:
+	ExcludeList()
+		:parent(nullptr) {}
+
+	ExcludeList(const ExcludeList &_parent)
+		:parent(&_parent) {}
+
 	gcc_pure
 	bool IsEmpty() const {
 #ifdef HAVE_CLASS_GLOB
-		return patterns.empty();
+		return ((parent == nullptr) || parent->IsEmpty()) && patterns.empty();
 #else
 		/* not implemented */
 		return true;
diff --git a/src/db/update/Walk.cxx b/src/db/update/Walk.cxx
index af039ee48..3e5654a3c 100644
--- a/src/db/update/Walk.cxx
+++ b/src/db/update/Walk.cxx
@@ -219,6 +219,7 @@ UpdateWalk::UpdateRegularFile(Directory &directory,
 
 void
 UpdateWalk::UpdateDirectoryChild(Directory &directory,
+				 const ExcludeList &exclude_list,
 				 const char *name, const StorageFileInfo &info)
 {
 	assert(strchr(name, '/') == nullptr);
@@ -236,7 +237,7 @@ UpdateWalk::UpdateDirectoryChild(Directory &directory,
 
 		assert(&directory == subdir->parent);
 
-		if (!UpdateDirectory(*subdir, info))
+		if (!UpdateDirectory(*subdir, exclude_list, info))
 			editor.LockDeleteDirectory(subdir);
 	} else {
 		FormatDebug(update_domain,
@@ -327,7 +328,9 @@ UpdateWalk::SkipSymlink(const Directory *directory,
 }
 
 bool
-UpdateWalk::UpdateDirectory(Directory &directory, const StorageFileInfo &info)
+UpdateWalk::UpdateDirectory(Directory &directory,
+			    const ExcludeList &exclude_list,
+			    const StorageFileInfo &info)
 {
 	assert(info.IsDirectory());
 
@@ -340,17 +343,17 @@ UpdateWalk::UpdateDirectory(Directory &directory, const StorageFileInfo &info)
 		return false;
 	}
 
-	ExcludeList exclude_list;
+	ExcludeList child_exclude_list(exclude_list);
 
 	{
 		const auto exclude_path_fs =
 			storage.MapChildFS(directory.GetPath(), ".mpdignore");
 		if (!exclude_path_fs.IsNull())
-			exclude_list.LoadFile(exclude_path_fs);
+			child_exclude_list.LoadFile(exclude_path_fs);
 	}
 
-	if (!exclude_list.IsEmpty())
-		RemoveExcludedFromDirectory(directory, exclude_list);
+	if (!child_exclude_list.IsEmpty())
+		RemoveExcludedFromDirectory(directory, child_exclude_list);
 
 	PurgeDeletedFromDirectory(directory);
 
@@ -361,7 +364,7 @@ UpdateWalk::UpdateDirectory(Directory &directory, const StorageFileInfo &info)
 
 		{
 			const auto name_fs = AllocatedPath::FromUTF8(name_utf8);
-			if (name_fs.IsNull() || exclude_list.Check(name_fs))
+			if (name_fs.IsNull() || child_exclude_list.Check(name_fs))
 				continue;
 		}
 
@@ -376,7 +379,7 @@ UpdateWalk::UpdateDirectory(Directory &directory, const StorageFileInfo &info)
 			continue;
 		}
 
-		UpdateDirectoryChild(directory, name_utf8, info2);
+		UpdateDirectoryChild(directory, child_exclude_list, name_utf8, info2);
 	}
 
 	directory.mtime = info.mtime;
@@ -468,7 +471,9 @@ UpdateWalk::UpdateUri(Directory &root, const char *uri)
 		return;
 	}
 
-	UpdateDirectoryChild(*parent, name, info);
+	ExcludeList exclude_list;
+
+	UpdateDirectoryChild(*parent, exclude_list, name, info);
 }
 
 bool
@@ -484,7 +489,9 @@ UpdateWalk::Walk(Directory &root, const char *path, bool discard)
 		if (!GetInfo(storage, "", info))
 			return false;
 
-		UpdateDirectory(root, info);
+		ExcludeList exclude_list;
+
+		UpdateDirectory(root, exclude_list, info);
 	}
 
 	return modified;
diff --git a/src/db/update/Walk.hxx b/src/db/update/Walk.hxx
index d9fe7c84c..99d54ef51 100644
--- a/src/db/update/Walk.hxx
+++ b/src/db/update/Walk.hxx
@@ -129,10 +129,12 @@ private:
 			       const char *name, const StorageFileInfo &info);
 
 	void UpdateDirectoryChild(Directory &directory,
+				  const ExcludeList &exclude_list,
 				  const char *name,
 				  const StorageFileInfo &info);
 
 	bool UpdateDirectory(Directory &directory,
+			     const ExcludeList &exclude_list,
 			     const StorageFileInfo &info);
 
 	/**