diff --git a/lib/bdev.py b/lib/bdev.py
index c0e5cf4a3a847f85ba85b7ad25de23836848d486..b2212356bfc5a4936677ca8bf8cff00f4829e2c5 100644
--- a/lib/bdev.py
+++ b/lib/bdev.py
@@ -666,35 +666,59 @@ class LogicalVolume(BlockDev):
     return data
 
   @classmethod
-  def GetPVInfo(cls, vg_names, filter_allocatable=True):
+  def GetPVInfo(cls, vg_names, filter_allocatable=True, include_lvs=False):
     """Get the free space info for PVs in a volume group.
 
     @param vg_names: list of volume group names, if empty all will be returned
     @param filter_allocatable: whether to skip over unallocatable PVs
+    @param include_lvs: whether to include a list of LVs hosted on each PV
 
     @rtype: list
     @return: list of objects.LvmPvInfo objects
 
     """
+    # We request "lv_name" field only if we care about LVs, so we don't get
+    # a long list of entries with many duplicates unless we really have to.
+    # The duplicate "pv_name" field will be ignored.
+    if include_lvs:
+      lvfield = "lv_name"
+    else:
+      lvfield = "pv_name"
     try:
       info = cls._GetVolumeInfo("pvs", ["pv_name", "vg_name", "pv_free",
-                                        "pv_attr", "pv_size"])
+                                        "pv_attr", "pv_size", lvfield])
     except errors.GenericError, err:
       logging.error("Can't get PV information: %s", err)
       return None
 
+    # When asked for LVs, "pvs" may return multiple entries for the same PV-LV
+    # pair. We sort entries by PV name and then LV name, so it's easy to weed
+    # out duplicates.
+    if include_lvs:
+      info.sort(key=(lambda i: (i[0], i[5])))
     data = []
-    for (pv_name, vg_name, pv_free, pv_attr, pv_size) in info:
+    lastpvi = None
+    for (pv_name, vg_name, pv_free, pv_attr, pv_size, lv_name) in info:
       # (possibly) skip over pvs which are not allocatable
       if filter_allocatable and pv_attr[0] != "a":
         continue
       # (possibly) skip over pvs which are not in the right volume group(s)
       if vg_names and vg_name not in vg_names:
         continue
-      pvi = objects.LvmPvInfo(name=pv_name, vg_name=vg_name,
-                              size=float(pv_size), free=float(pv_free),
-                              attributes=pv_attr)
-      data.append(pvi)
+      # Beware of duplicates (check before inserting)
+      if lastpvi and lastpvi.name == pv_name:
+        if include_lvs and lv_name:
+          if not lastpvi.lv_list or lastpvi.lv_list[-1] != lv_name:
+            lastpvi.lv_list.append(lv_name)
+      else:
+        if include_lvs and lv_name:
+          lvl = [lv_name]
+        else:
+          lvl = []
+        lastpvi = objects.LvmPvInfo(name=pv_name, vg_name=vg_name,
+                                    size=float(pv_size), free=float(pv_free),
+                                    attributes=pv_attr, lv_list=lvl)
+        data.append(lastpvi)
 
     return data
 
diff --git a/lib/objects.py b/lib/objects.py
index 2a0b8bda088dd1493910623016cf5bd700a7afbf..f8667e34361ab7573997815b77c84f9dfed24b0a 100644
--- a/lib/objects.py
+++ b/lib/objects.py
@@ -2074,6 +2074,8 @@ class LvmPvInfo(ConfigObject):
   @ivar free: free space in the PV, in MiB
   @type attributes: string
   @ivar attributes: PV attributes
+  @type lv_list: list of strings
+  @ivar lv_list: names of the LVs hosted on the PV
   """
   __slots__ = [
     "name",
@@ -2081,6 +2083,7 @@ class LvmPvInfo(ConfigObject):
     "size",
     "free",
     "attributes",
+    "lv_list"
     ]
 
   def IsEmpty(self):