diff --git a/libpod/volume.go b/libpod/volume.go
index 82f3898330..b29ac7ddfd 100644
--- a/libpod/volume.go
+++ b/libpod/volume.go
@@ -137,7 +137,7 @@ func (v *Volume) Config() (*VolumeConfig, error) {
 
 // VolumeInUse goes through the container dependencies of a volume
 // and checks if the volume is being used by any container.
-func (v *Volume) VolumesInUse() ([]string, error) {
+func (v *Volume) VolumeInUse() ([]string, error) {
 	v.lock.Lock()
 	defer v.lock.Unlock()
 
@@ -146,3 +146,13 @@ func (v *Volume) VolumesInUse() ([]string, error) {
 	}
 	return v.runtime.state.VolumeInUse(v)
 }
+
+// IsDangling returns whether this volume is dangling (unused by any
+// containers).
+func (v *Volume) IsDangling() (bool, error) {
+	ctrs, err := v.VolumeInUse()
+	if err != nil {
+		return false, err
+	}
+	return len(ctrs) == 0, nil
+}
diff --git a/pkg/domain/filters/volumes.go b/pkg/domain/filters/volumes.go
index f97c3f5708..b1b5e63199 100644
--- a/pkg/domain/filters/volumes.go
+++ b/pkg/domain/filters/volumes.go
@@ -61,6 +61,29 @@ func GenerateVolumeFilters(filters map[string][]string) ([]libpod.VolumeFilter,
 					}
 					return false
 				})
+			case "dangling":
+				danglingVal := val
+				invert := false
+				switch strings.ToLower(danglingVal) {
+				case "true", "1":
+					// Do nothing
+				case "false", "0":
+					// Dangling=false requires that we
+					// invert the result of IsDangling.
+					invert = true
+				default:
+					return nil, errors.Errorf("%q is not a valid value for the \"dangling\" filter - must be true or false", danglingVal)
+				}
+				vf = append(vf, func(v *libpod.Volume) bool {
+					dangling, err := v.IsDangling()
+					if err != nil {
+						return false
+					}
+					if invert {
+						return !dangling
+					}
+					return dangling
+				})
 			default:
 				return nil, errors.Errorf("%q is in an invalid volume filter", filter)
 			}
diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go
index 90002326e8..0511289ab0 100644
--- a/pkg/domain/infra/abi/system.go
+++ b/pkg/domain/infra/abi/system.go
@@ -330,7 +330,7 @@ func (ic *ContainerEngine) SystemDf(ctx context.Context, options entities.System
 		if err != nil {
 			return nil, err
 		}
-		inUse, err := v.VolumesInUse()
+		inUse, err := v.VolumeInUse()
 		if err != nil {
 			return nil, err
 		}
diff --git a/test/e2e/volume_ls_test.go b/test/e2e/volume_ls_test.go
index 7664e64bb6..d2d75af9e3 100644
--- a/test/e2e/volume_ls_test.go
+++ b/test/e2e/volume_ls_test.go
@@ -1,6 +1,7 @@
 package integration
 
 import (
+	"fmt"
 	"os"
 
 	. "github.com/containers/libpod/test/utils"
@@ -82,4 +83,30 @@ var _ = Describe("Podman volume ls", func() {
 		Expect(len(session.OutputToStringArray())).To(Equal(2))
 		Expect(session.OutputToStringArray()[1]).To(ContainSubstring(volName))
 	})
+
+	It("podman volume ls with --filter dangling", func() {
+		volName1 := "volume1"
+		session := podmanTest.Podman([]string{"volume", "create", volName1})
+		session.WaitWithDefaultTimeout()
+		Expect(session.ExitCode()).To(Equal(0))
+
+		volName2 := "volume2"
+		session2 := podmanTest.Podman([]string{"volume", "create", volName2})
+		session2.WaitWithDefaultTimeout()
+		Expect(session2.ExitCode()).To(Equal(0))
+
+		ctr := podmanTest.Podman([]string{"create", "-v", fmt.Sprintf("%s:/test", volName2), ALPINE, "sh"})
+		ctr.WaitWithDefaultTimeout()
+		Expect(ctr.ExitCode()).To(Equal(0))
+
+		lsNoDangling := podmanTest.Podman([]string{"volume", "ls", "--filter", "dangling=false", "--quiet"})
+		lsNoDangling.WaitWithDefaultTimeout()
+		Expect(lsNoDangling.ExitCode()).To(Equal(0))
+		Expect(lsNoDangling.OutputToString()).To(ContainSubstring(volName2))
+
+		lsDangling := podmanTest.Podman([]string{"volume", "ls", "--filter", "dangling=true", "--quiet"})
+		lsDangling.WaitWithDefaultTimeout()
+		Expect(lsDangling.ExitCode()).To(Equal(0))
+		Expect(lsDangling.OutputToString()).To(ContainSubstring(volName1))
+	})
 })