intel-iommu: Fix double lock in get_domain_for_dev()
authorJiri Slaby <jirislaby@gmail.com>
Mon, 14 Jun 2010 15:17:32 +0000 (17:17 +0200)
committerDavid Woodhouse <David.Woodhouse@intel.com>
Tue, 15 Jun 2010 09:50:46 +0000 (10:50 +0100)
stanse found the following double lock.

In get_domain_for_dev:
  spin_lock_irqsave(&device_domain_lock, flags);
  domain_exit(domain);
    domain_remove_dev_info(domain);
      spin_lock_irqsave(&device_domain_lock, flags);
      spin_unlock_irqrestore(&device_domain_lock, flags);
  spin_unlock_irqrestore(&device_domain_lock, flags);

This happens when the domain is created by another CPU at the same time
as this function is creating one, and the other CPU wins the race to
attach it to the device in question, so we have to destroy our own
newly-created one.

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
drivers/pci/intel-iommu.c

index 3bd30557ce2ebe456ab1adfb26c9bfe2a945cce3..bf8fd913d064a5e786c8fdde0d6abdfa504d134a 100644 (file)
@@ -1874,14 +1874,15 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
                        }
                }
                if (found) {
+                       spin_unlock_irqrestore(&device_domain_lock, flags);
                        free_devinfo_mem(info);
                        domain_exit(domain);
                        domain = found;
                } else {
                        list_add(&info->link, &domain->devices);
                        list_add(&info->global, &device_domain_list);
+                       spin_unlock_irqrestore(&device_domain_lock, flags);
                }
-               spin_unlock_irqrestore(&device_domain_lock, flags);
        }
 
 found_domain: